diff --git a/CHANGES.txt b/CHANGES.txt
index de5cd3768a..12691ced64 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0
+ * Lift MessagingService.minimum_version to 40 (CASSANDRA-18314)
* Introduce pluggable crypto providers and default to AmazonCorrettoCryptoProvider (CASSANDRA-18624)
* Improved DeletionTime serialization (CASSANDRA-18648)
* CEP-7: Storage Attached Indexes (CASSANDRA-16052)
diff --git a/src/java/org/apache/cassandra/db/CounterMutation.java b/src/java/org/apache/cassandra/db/CounterMutation.java
index deb852eab4..ed64e0aad7 100644
--- a/src/java/org/apache/cassandra/db/CounterMutation.java
+++ b/src/java/org/apache/cassandra/db/CounterMutation.java
@@ -48,8 +48,6 @@ import org.apache.cassandra.utils.*;
import org.apache.cassandra.utils.btree.BTreeSet;
import static java.util.concurrent.TimeUnit.*;
-import static org.apache.cassandra.net.MessagingService.VERSION_30;
-import static org.apache.cassandra.net.MessagingService.VERSION_3014;
import static org.apache.cassandra.net.MessagingService.VERSION_40;
import static org.apache.cassandra.net.MessagingService.VERSION_50;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
@@ -332,8 +330,6 @@ public class CounterMutation implements IMutation
return DatabaseDescriptor.getCounterWriteRpcTimeout(unit);
}
- private int serializedSize30;
- private int serializedSize3014;
private int serializedSize40;
private int serializedSize50;
@@ -341,14 +337,6 @@ public class CounterMutation implements IMutation
{
switch (version)
{
- case VERSION_30:
- if (serializedSize30 == 0)
- serializedSize30 = (int) serializer.serializedSize(this, VERSION_30);
- return serializedSize30;
- case VERSION_3014:
- if (serializedSize3014 == 0)
- serializedSize3014 = (int) serializer.serializedSize(this, VERSION_3014);
- return serializedSize3014;
case VERSION_40:
if (serializedSize40 == 0)
serializedSize40 = (int) serializer.serializedSize(this, VERSION_40);
diff --git a/src/java/org/apache/cassandra/db/Mutation.java b/src/java/org/apache/cassandra/db/Mutation.java
index dac4af0fa0..cceb8ea510 100644
--- a/src/java/org/apache/cassandra/db/Mutation.java
+++ b/src/java/org/apache/cassandra/db/Mutation.java
@@ -48,8 +48,6 @@ import org.apache.cassandra.service.AbstractWriteResponseHandler;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.concurrent.Future;
-import static org.apache.cassandra.net.MessagingService.VERSION_30;
-import static org.apache.cassandra.net.MessagingService.VERSION_3014;
import static org.apache.cassandra.net.MessagingService.VERSION_40;
import static org.apache.cassandra.net.MessagingService.VERSION_50;
import static org.apache.cassandra.utils.MonotonicClock.Global.approxTime;
@@ -317,8 +315,6 @@ public class Mutation implements IMutation, Supplier
return buff.append("])").toString();
}
- private int serializedSize30;
- private int serializedSize3014;
private int serializedSize40;
private int serializedSize50;
@@ -326,14 +322,6 @@ public class Mutation implements IMutation, Supplier
{
switch (version)
{
- case VERSION_30:
- if (serializedSize30 == 0)
- serializedSize30 = (int) serializer.serializedSize(this, VERSION_30);
- return serializedSize30;
- case VERSION_3014:
- if (serializedSize3014 == 0)
- serializedSize3014 = (int) serializer.serializedSize(this, VERSION_3014);
- return serializedSize3014;
case VERSION_40:
if (serializedSize40 == 0)
serializedSize40 = (int) serializer.serializedSize(this, VERSION_40);
diff --git a/src/java/org/apache/cassandra/db/MutationVerbHandler.java b/src/java/org/apache/cassandra/db/MutationVerbHandler.java
index 230ca6345e..1ab6711fdb 100644
--- a/src/java/org/apache/cassandra/db/MutationVerbHandler.java
+++ b/src/java/org/apache/cassandra/db/MutationVerbHandler.java
@@ -66,14 +66,13 @@ public class MutationVerbHandler implements IVerbHandler
.withParam(ParamType.RESPOND_TO, originalMessage.from())
.withoutParam(ParamType.FORWARD_TO);
- boolean useSameMessageID = forwardTo.useSameMessageID(originalMessage.id());
// reuse the same Message if all ids are identical (as they will be for 4.0+ node originated messages)
- Message message = useSameMessageID ? builder.build() : null;
+ Message message = builder.build();
forwardTo.forEach((id, target) ->
{
Tracing.trace("Enqueuing forwarded write to {}", target);
- MessagingService.instance().send(useSameMessageID ? message : builder.withId(id).build(), target);
+ MessagingService.instance().send(message, target);
});
}
}
diff --git a/src/java/org/apache/cassandra/db/ReadResponse.java b/src/java/org/apache/cassandra/db/ReadResponse.java
index 9ef9128a36..a9e2cec4a7 100644
--- a/src/java/org/apache/cassandra/db/ReadResponse.java
+++ b/src/java/org/apache/cassandra/db/ReadResponse.java
@@ -298,6 +298,7 @@ public abstract class ReadResponse
{
public void serialize(ReadResponse response, DataOutputPlus out, int version) throws IOException
{
+ assert version >= MessagingService.VERSION_40;
boolean isDigest = response instanceof DigestResponse;
ByteBuffer digest = isDigest ? ((DigestResponse)response).digest : ByteBufferUtil.EMPTY_BYTE_BUFFER;
ByteBufferUtil.writeWithVIntLength(digest, out);
@@ -312,12 +313,8 @@ public abstract class ReadResponse
// repaired sstables were read (but they might be on other replicas).
// If the coordinator did not request this info, the response contains an empty digest
// and a true for the isConclusive flag.
- // If the messaging version is < 4.0, these are omitted altogether.
- if (version >= MessagingService.VERSION_40)
- {
- ByteBufferUtil.writeWithVIntLength(response.repairedDataDigest(), out);
- out.writeBoolean(response.isRepairedDigestConclusive());
- }
+ ByteBufferUtil.writeWithVIntLength(response.repairedDataDigest(), out);
+ out.writeBoolean(response.isRepairedDigestConclusive());
ByteBuffer data = ((DataResponse)response).data;
ByteBufferUtil.writeWithVIntLength(data, out);
@@ -326,6 +323,7 @@ public abstract class ReadResponse
public ReadResponse deserialize(DataInputPlus in, int version) throws IOException
{
+ assert version >= MessagingService.VERSION_40;
ByteBuffer digest = ByteBufferUtil.readWithVIntLength(in);
if (digest.hasRemaining())
return new DigestResponse(digest);
@@ -334,17 +332,8 @@ public abstract class ReadResponse
// that comes from the replica's repaired set, along with a flag indicating
// whether or not the digest may be influenced by unrepaired/pending
// repaired data
- boolean repairedDigestConclusive;
- if (version >= MessagingService.VERSION_40)
- {
- digest = ByteBufferUtil.readWithVIntLength(in);
- repairedDigestConclusive = in.readBoolean();
- }
- else
- {
- digest = ByteBufferUtil.EMPTY_BYTE_BUFFER;
- repairedDigestConclusive = true;
- }
+ digest = ByteBufferUtil.readWithVIntLength(in);
+ boolean repairedDigestConclusive = in.readBoolean();
ByteBuffer data = ByteBufferUtil.readWithVIntLength(in);
return new RemoteDataResponse(data, digest, repairedDigestConclusive, version);
@@ -352,6 +341,7 @@ public abstract class ReadResponse
public long serializedSize(ReadResponse response, int version)
{
+ assert version >= MessagingService.VERSION_40;
boolean isDigest = response instanceof DigestResponse;
ByteBuffer digest = isDigest ? ((DigestResponse)response).digest : ByteBufferUtil.EMPTY_BYTE_BUFFER;
long size = ByteBufferUtil.serializedSizeWithVIntLength(digest);
@@ -360,16 +350,12 @@ public abstract class ReadResponse
{
// From 4.0, a coordinator may request an additional info about the repaired data
// that makes up the response.
- if (version >= MessagingService.VERSION_40)
- {
- size += ByteBufferUtil.serializedSizeWithVIntLength(response.repairedDataDigest());
- size += 1;
- }
+ size += ByteBufferUtil.serializedSizeWithVIntLength(response.repairedDataDigest());
+ size += 1;
// In theory, we should deserialize/re-serialize if the version asked is different from the current
// version as the content could have a different serialization format. So far though, we haven't made
// change to partition iterators serialization since 3.0 so we skip this.
- assert version >= MessagingService.VERSION_30;
ByteBuffer data = ((DataResponse)response).data;
size += ByteBufferUtil.serializedSizeWithVIntLength(data);
}
diff --git a/src/java/org/apache/cassandra/db/filter/ColumnFilter.java b/src/java/org/apache/cassandra/db/filter/ColumnFilter.java
index 48ba7388c7..90fc9f3a11 100644
--- a/src/java/org/apache/cassandra/db/filter/ColumnFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/ColumnFilter.java
@@ -22,22 +22,17 @@ import java.util.*;
import javax.annotation.Nullable;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.rows.CellPath;
-import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
-import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.utils.CassandraVersion;
/**
* Represents which (non-PK) columns (and optionally which sub-part of a column for complex columns) are selected
@@ -69,7 +64,6 @@ import org.apache.cassandra.utils.CassandraVersion;
*/
public abstract class ColumnFilter
{
- private final static Logger logger = LoggerFactory.getLogger(ColumnFilter.class);
public static final ColumnFilter NONE = selection(RegularAndStaticColumns.NONE);
@@ -87,10 +81,6 @@ public abstract class ColumnFilter
* For queries that have no restrictions on the clustering or regular columns, C* will return some data for
* the partition even if it does not contains any row as long as one of the static columns contains data.
* To be able to ensure those queries all columns need to be fetched.
- *
- *
This strategy is also used, instead of the ALL_REGULARS_AND_QUERIED_STATICS_COLUMNS one, in mixed version clusters
- * where some nodes have a version lower than 4.0. To ensure backward compatibility with those version that interpret the
- * _fetchAll_ serialization flag as a true fetch all request.
*/
ALL_COLUMNS
{
@@ -182,67 +172,6 @@ public abstract class ColumnFilter
abstract RegularAndStaticColumns getFetchedColumns(TableMetadata metadata, RegularAndStaticColumns queried);
}
- /**
- * Returns {@code true} if there are pre-4.0-rc2 nodes in the cluster, {@code false} otherwise.
- *
- *
ColumnFilters from 4.0 releases before RC2 wrongly assumed that fetching all regular columns and not
- * the static columns was enough. That was not the case for queries that needed to return rows for empty partitions.
- * See CASSANDRA-16686 for more details.
- */
- private static boolean isUpgradingFromVersionLowerThan40RC2()
- {
- if (Gossiper.instance.isUpgradingFromVersionLowerThan(CassandraVersion.CASSANDRA_4_0_RC2))
- {
- logger.trace("ColumnFilter conversion has been applied so that static columns will not be fetched because there are pre 4.0-rc2 nodes in the cluster");
- return true;
- }
- return false;
- }
-
- /**
- * Returns {@code true} if there are pre-4.0 nodes in the cluster, {@code false} otherwise.
- *
- *
If there pre-4.0 nodes in the cluster all static columns should be fetched along with all regular columns.
- * This is due to the fact that this nodes have a different understanding of the fetchAll serialization flag.
- * Pre-4.0 the fetchAll flag meant that all the columns regular AND STATIC should be fetched whereas for 4.0
- * nodes it meant that only the regular columns and the queried static columns should be fetched.
- */
- private static boolean isUpgradingFromVersionLowerThan40()
- {
- if (Gossiper.instance.isUpgradingFromVersionLowerThan(CassandraVersion.CASSANDRA_4_0))
- {
- logger.trace("ColumnFilter conversion has been applied so that all static columns will be fetched because there are pre 4.0 nodes in the cluster");
- return true;
- }
- return false;
- }
-
- /**
- * Returns {@code true} if there are pre-3.4 nodes in the cluster, {@code false} otherwise.
- *
- * When fetchAll is enabled on pre CASSANDRA-10657 (3.4-), queried columns are not considered at all, and it
- * is assumed that all columns are queried. CASSANDRA-10657 (3.4+) brings back skipping values of columns
- * which are not in queried set when fetchAll is enabled. That makes exactly the same filter being
- * interpreted in a different way on 3.4- and 3.4+.
- *
- * Moreover, there is no way to convert the filter with fetchAll and queried != null so that it is
- * interpreted the same way on 3.4- because that Cassandra version does not support such filtering.
- *
- * In order to avoid inconsistencies in data read by 3.4- and 3.4+ we need to avoid creation of incompatible
- * filters when the cluster contains 3.4- nodes. We need to do that by using a wildcard query.
- *
- * see CASSANDRA-10657, CASSANDRA-15833, CASSANDRA-16415
- */
- private static boolean isUpgradingFromVersionLowerThan34()
- {
- if (Gossiper.instance.isUpgradingFromVersionLowerThan(CassandraVersion.CASSANDRA_3_4))
- {
- logger.trace("ColumnFilter conversion has been applied so that all columns will be queried because there are pre 3.4 nodes in the cluster");
- return true;
- }
- return false;
- }
-
/**
* A filter that includes all columns for the provided table.
*/
@@ -267,29 +196,13 @@ public abstract class ColumnFilter
* A filter that fetches all columns for the provided table, but returns
* only the queried ones.
*/
+ @VisibleForTesting
public static ColumnFilter selection(TableMetadata metadata,
RegularAndStaticColumns queried,
boolean returnStaticContentOnPartitionWithNoRows)
{
- // pre CASSANDRA-10657 (3.4-), when fetchAll is enabled, queried columns are not considered at all, and it
- // is assumed that all columns are queried.
- if (isUpgradingFromVersionLowerThan34())
- {
- return new WildCardColumnFilter(metadata.regularAndStaticColumns());
- }
-
- // pre CASSANDRA-12768 (4.0-) all static columns should be fetched along with all regular columns.
- if (isUpgradingFromVersionLowerThan40())
- {
- return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_COLUMNS, metadata, queried, null);
- }
-
- // pre CASSANDRA-16686 (4.0-RC2-) static columns were not fetched unless queried which led to some wrong
- // results for some queries
- if (!returnStaticContentOnPartitionWithNoRows || isUpgradingFromVersionLowerThan40RC2())
- {
+ if (!returnStaticContentOnPartitionWithNoRows)
return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_REGULARS_AND_QUERIED_STATICS_COLUMNS, metadata, queried, null);
- }
return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_COLUMNS, metadata, queried, null);
}
@@ -546,48 +459,26 @@ public abstract class ColumnFilter
public ColumnFilter build()
{
- boolean isFetchAll = metadata != null;
+ boolean isFetchAllRegulars = metadata != null;
RegularAndStaticColumns queried = queriedBuilder == null ? null : queriedBuilder.build();
- // It's only ok to have queried == null in ColumnFilter if isFetchAll. So deal with the case of a selectionBuilder
+ // It's only ok to have queried == null in ColumnFilter if isFetchAllRegulars. So deal with the case of a selectionBuilder
// with nothing selected (we can at least happen on some backward compatible queries - CASSANDRA-10471).
- if (!isFetchAll && queried == null)
+ if (!isFetchAllRegulars && queried == null)
queried = RegularAndStaticColumns.NONE;
SortedSetMultimap s = buildSubSelections();
- if (isFetchAll)
+ if (isFetchAllRegulars)
{
- // When fetchAll is enabled on pre CASSANDRA-10657 (3.4-), queried columns are not considered at all, and it
- // is assumed that all columns are queried. CASSANDRA-10657 (3.4+) brings back skipping values of columns
- // which are not in queried set when fetchAll is enabled. That makes exactly the same filter being
- // interpreted in a different way on 3.4- and 3.4+.
- //
- // Moreover, there is no way to convert the filter with fetchAll and queried != null so that it is
- // interpreted the same way on 3.4- because that Cassandra version does not support such filtering.
- //
- // In order to avoid inconsitencies in data read by 3.4- and 3.4+ we need to avoid creation of incompatible
- // filters when the cluster contains 3.4- nodes. We do that by forcibly setting queried to null.
- //
- // see CASSANDRA-10657, CASSANDRA-15833, CASSANDRA-16415
- if (queried == null || isUpgradingFromVersionLowerThan34())
- {
+ // there is no way to convert the filter with fetchAll and queried != null so all columns are queried
+ // see CASSANDRA-10657, CASSANDRA-15833, CASSANDRA-16415
+ if (queried == null)
return new WildCardColumnFilter(metadata.regularAndStaticColumns());
- }
- // pre CASSANDRA-12768 (4.0-) all static columns should be fetched along with all regular columns.
- if (isUpgradingFromVersionLowerThan40())
- {
- return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_COLUMNS, metadata, queried, s);
- }
-
- // pre CASSANDRA-16686 (4.0-RC2-) static columns where not fetched unless queried witch lead to some wrong results
- // for some queries
- if (!returnStaticContentOnPartitionWithNoRows || isUpgradingFromVersionLowerThan40RC2())
- {
+ if (!returnStaticContentOnPartitionWithNoRows)
return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_REGULARS_AND_QUERIED_STATICS_COLUMNS, metadata, queried, s);
- }
return SelectionColumnFilter.newInstance(FetchingStrategy.ALL_COLUMNS, metadata, queried, s);
}
@@ -948,9 +839,8 @@ public abstract class ColumnFilter
public static class Serializer
{
- // Prior to 4.0 the FETCH_ALL flag meant fetch all regular and static columns. From 4.0 onward it meant
// fetch all regular columns and queried static columns
- private static final int FETCH_ALL_MASK = 0x01;
+ private static final int FETCH_ALL_REGULARS_MASK = 0x01;
private static final int HAS_QUERIED_MASK = 0x02;
private static final int HAS_SUB_SELECTIONS_MASK = 0x04;
// The FETCH_ALL_STATICS flag was added in CASSANDRA-16686 to allow 4.0 to handle queries that required
@@ -959,7 +849,7 @@ public abstract class ColumnFilter
private static int makeHeaderByte(ColumnFilter selection)
{
- return (selection.fetchesAllColumns(false) ? FETCH_ALL_MASK : 0)
+ return (selection.fetchesAllColumns(false) ? FETCH_ALL_REGULARS_MASK : 0)
| (!selection.isWildcard() ? HAS_QUERIED_MASK : 0)
| (selection.subSelections() != null ? HAS_SUB_SELECTIONS_MASK : 0)
| (selection.fetchesAllColumns(true) ? FETCH_ALL_STATICS_MASK : 0);
@@ -969,7 +859,7 @@ public abstract class ColumnFilter
{
out.writeByte(makeHeaderByte(selection));
- if (version >= MessagingService.VERSION_3014 && selection.fetchesAllColumns(false))
+ if (selection.fetchesAllColumns(false))
{
serializeRegularAndStaticColumns(selection.fetchedColumns(), out);
}
@@ -1004,9 +894,7 @@ public abstract class ColumnFilter
public ColumnFilter deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
int header = in.readUnsignedByte();
- // The meaning of isFetchAll is actually different for pre-4.0 versions and for 4.0+ versions
- // In 4.0+ it meant is fetch all regulars
- boolean isFetchAll = (header & FETCH_ALL_MASK) != 0;
+ boolean isFetchAllRegulars = (header & FETCH_ALL_REGULARS_MASK) != 0;
boolean hasQueried = (header & HAS_QUERIED_MASK) != 0;
boolean hasSubSelections = (header & HAS_SUB_SELECTIONS_MASK) != 0;
boolean isFetchAllStatics = (header & FETCH_ALL_STATICS_MASK) != 0;
@@ -1014,50 +902,23 @@ public abstract class ColumnFilter
RegularAndStaticColumns fetched = null;
RegularAndStaticColumns queried = null;
- if (isFetchAll)
- {
- if (version >= MessagingService.VERSION_3014)
- {
- fetched = deserializeRegularAndStaticColumns(in, metadata);
- }
- else
- {
- fetched = metadata.regularAndStaticColumns();
- }
- }
+ if (isFetchAllRegulars)
+ fetched = deserializeRegularAndStaticColumns(in, metadata);
if (hasQueried)
- {
queried = deserializeRegularAndStaticColumns(in, metadata);
- }
SortedSetMultimap subSelections = null;
if (hasSubSelections)
- {
subSelections = deserializeSubSelection(in, version, metadata);
- }
- if (isFetchAll)
+ if (isFetchAllRegulars)
{
- // pre CASSANDRA-10657 (3.4-), when fetchAll is enabled, queried columns are not considered at all, and it
- // is assumed that all columns are queried.
- if (!hasQueried || isUpgradingFromVersionLowerThan34())
- {
+ if (!hasQueried)
return new WildCardColumnFilter(fetched);
- }
- // pre CASSANDRA-12768 (4.0-) all static columns should be fetched along with all regular columns.
- if (isUpgradingFromVersionLowerThan40())
- {
- return new SelectionColumnFilter(FetchingStrategy.ALL_COLUMNS, queried, fetched, subSelections);
- }
-
- // pre CASSANDRA-16686 (4.0-RC2-) static columns where not fetched unless queried witch lead to some wrong results
- // for some queries
- if (!isFetchAllStatics || isUpgradingFromVersionLowerThan40RC2())
- {
+ if (!isFetchAllStatics)
return new SelectionColumnFilter(FetchingStrategy.ALL_REGULARS_AND_QUERIED_STATICS_COLUMNS, queried, fetched, subSelections);
- }
return new SelectionColumnFilter(FetchingStrategy.ALL_COLUMNS, queried, fetched, subSelections);
}
@@ -1091,7 +952,7 @@ public abstract class ColumnFilter
{
long size = 1; // header byte
- if (version >= MessagingService.VERSION_3014 && selection.fetchesAllColumns(false))
+ if (selection.fetchesAllColumns(false))
{
size += regularAndStaticColumnsSerializedSize(selection.fetchedColumns());
}
diff --git a/src/java/org/apache/cassandra/exceptions/RequestFailureReason.java b/src/java/org/apache/cassandra/exceptions/RequestFailureReason.java
index 51415facd5..1703c4e180 100644
--- a/src/java/org/apache/cassandra/exceptions/RequestFailureReason.java
+++ b/src/java/org/apache/cassandra/exceptions/RequestFailureReason.java
@@ -97,20 +97,20 @@ public enum RequestFailureReason
public void serialize(RequestFailureReason reason, DataOutputPlus out, int version) throws IOException
{
- if (version < VERSION_40)
- out.writeShort(reason.code);
- else
- out.writeUnsignedVInt32(reason.code);
+ assert version >= VERSION_40;
+ out.writeUnsignedVInt32(reason.code);
}
public RequestFailureReason deserialize(DataInputPlus in, int version) throws IOException
{
- return fromCode(version < VERSION_40 ? in.readUnsignedShort() : in.readUnsignedVInt32());
+ assert version >= VERSION_40;
+ return fromCode(in.readUnsignedVInt32());
}
public long serializedSize(RequestFailureReason reason, int version)
{
- return version < VERSION_40 ? 2 : VIntCoding.computeVIntSize(reason.code);
+ assert version >= VERSION_40;
+ return VIntCoding.computeVIntSize(reason.code);
}
}
}
diff --git a/src/java/org/apache/cassandra/hints/HintsDescriptor.java b/src/java/org/apache/cassandra/hints/HintsDescriptor.java
index 02820bcd04..a1e961e7a1 100644
--- a/src/java/org/apache/cassandra/hints/HintsDescriptor.java
+++ b/src/java/org/apache/cassandra/hints/HintsDescriptor.java
@@ -66,7 +66,6 @@ final class HintsDescriptor
{
private static final Logger logger = LoggerFactory.getLogger(HintsDescriptor.class);
- static final int VERSION_30 = 1;
static final int VERSION_40 = 2;
static final int VERSION_50 = 3;
static final int CURRENT_VERSION = DatabaseDescriptor.getStorageCompatibilityMode().isBefore(5) ? VERSION_40 : VERSION_50;
@@ -231,8 +230,6 @@ final class HintsDescriptor
{
switch (hintsVersion)
{
- case VERSION_30:
- return MessagingService.VERSION_30;
case VERSION_40:
return MessagingService.VERSION_40;
case VERSION_50:
diff --git a/src/java/org/apache/cassandra/locator/InetAddressAndPort.java b/src/java/org/apache/cassandra/locator/InetAddressAndPort.java
index 78627e49ca..c954a05b1c 100644
--- a/src/java/org/apache/cassandra/locator/InetAddressAndPort.java
+++ b/src/java/org/apache/cassandra/locator/InetAddressAndPort.java
@@ -55,7 +55,6 @@ import org.apache.cassandra.utils.FastByteOperations;
* need to sometimes return a port and sometimes not.
*
*/
-@SuppressWarnings("UnstableApiUsage")
public final class InetAddressAndPort extends InetSocketAddress implements Comparable, Serializable
{
private static final long serialVersionUID = 0;
@@ -319,8 +318,6 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
/**
* As of version 4.0 the endpoint description includes a port number as an unsigned short
- * This serializer matches the 3.0 CompactEndpointSerializationHelper, encoding the number of address bytes
- * in a single byte before the address itself.
*/
public static final class Serializer implements IVersionedSerializer
{
@@ -347,17 +344,10 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
void serialize(byte[] address, int port, DataOutputPlus out, int version) throws IOException
{
- if (version >= MessagingService.VERSION_40)
- {
- out.writeByte(address.length + 2);
- out.write(address);
- out.writeShort(port);
- }
- else
- {
- out.writeByte(address.length);
- out.write(address);
- }
+ assert version >= MessagingService.VERSION_40;
+ out.writeByte(address.length + 2);
+ out.write(address);
+ out.writeShort(port);
}
public InetAddressAndPort deserialize(DataInputPlus in, int version) throws IOException
@@ -368,11 +358,7 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
//The original pre-4.0 serialiation of just an address
case 4:
case 16:
- {
- byte[] bytes = new byte[size];
- in.readFully(bytes, 0, bytes.length);
- return getByAddress(bytes);
- }
+ throw new AssertionError("pre-4.0 serialization size " + size);
//Address and one port
case 6:
case 18:
@@ -395,13 +381,7 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
public InetAddressAndPort extract(ByteBuffer buf, int position) throws IOException
{
int size = buf.get(position++) & 0xFF;
- if (size == 4 || size == 16)
- {
- byte[] bytes = new byte[size];
- ByteBufferUtil.copyBytes(buf, position, bytes, 0, size);
- return getByAddress(bytes);
- }
- else if (size == 6 || size == 18)
+ if (size == 6 || size == 18)
{
byte[] bytes = new byte[size - 2];
ByteBufferUtil.copyBytes(buf, position, bytes, 0, size - 2);
@@ -420,26 +400,15 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
public long serializedSize(InetSocketAddress from, int version)
{
- //4.0 includes a port number
- if (version >= MessagingService.VERSION_40)
- {
- if (from.getAddress() instanceof Inet4Address)
- return 1 + 4 + 2;
- assert from.getAddress() instanceof Inet6Address;
- return 1 + 16 + 2;
- }
- else
- {
- if (from.getAddress() instanceof Inet4Address)
- return 1 + 4;
- assert from.getAddress() instanceof Inet6Address;
- return 1 + 16;
- }
+ assert version >= MessagingService.VERSION_40;
+ if (from.getAddress() instanceof Inet4Address)
+ return 1 + 4 + 2;
+ assert from.getAddress() instanceof Inet6Address;
+ return 1 + 16 + 2;
}
}
- /** Serializer for handling FWD_FRM message parameters. Pre-4.0 deserialization is a special
- * case in the message
+ /** Serializer for handling FWD_FRM message parameters.
*/
public static final class FwdFrmSerializer implements IVersionedSerializer
{
@@ -448,73 +417,43 @@ public final class InetAddressAndPort extends InetSocketAddress implements Compa
public void serialize(InetAddressAndPort endpoint, DataOutputPlus out, int version) throws IOException
{
+ assert version >= MessagingService.VERSION_40;
byte[] buf = endpoint.addressBytes;
-
- if (version >= MessagingService.VERSION_40)
- {
- out.writeByte(buf.length + 2);
- out.write(buf);
- out.writeShort(endpoint.getPort());
- }
- else
- {
- out.write(buf);
- }
+ out.writeByte(buf.length + 2);
+ out.write(buf);
+ out.writeShort(endpoint.getPort());
}
public long serializedSize(InetAddressAndPort from, int version)
{
- //4.0 includes a port number
- if (version >= MessagingService.VERSION_40)
- {
- if (from.getAddress() instanceof Inet4Address)
- return 1 + 4 + 2;
- assert from.getAddress() instanceof Inet6Address;
- return 1 + 16 + 2;
- }
- else
- {
- if (from.getAddress() instanceof Inet4Address)
- return 4;
- assert from.getAddress() instanceof Inet6Address;
- return 16;
- }
+ assert version >= MessagingService.VERSION_40;
+ if (from.getAddress() instanceof Inet4Address)
+ return 1 + 4 + 2;
+ assert from.getAddress() instanceof Inet6Address;
+ return 1 + 16 + 2;
}
@Override
public InetAddressAndPort deserialize(DataInputPlus in, int version) throws IOException
{
- if (version >= MessagingService.VERSION_40)
+ assert version >= MessagingService.VERSION_40 : "FWD_FRM deserializations should be special-cased pre-4.0";
+ int size = in.readByte() & 0xFF;
+ switch (size)
{
- int size = in.readByte() & 0xFF;
- switch (size)
+ //Address and one port
+ case 6:
+ case 18:
{
- //Address and one port
- case 6:
- case 18:
- {
- byte[] bytes = new byte[size - 2];
- in.readFully(bytes);
+ byte[] bytes = new byte[size - 2];
+ in.readFully(bytes);
- int port = in.readShort() & 0xFFFF;
- return getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port);
- }
- default:
- throw new AssertionError("Unexpected size " + size);
+ int port = in.readShort() & 0xFFFF;
+ return getByAddressOverrideDefaults(InetAddress.getByAddress(bytes), bytes, port);
}
- }
- else
- {
- throw new IllegalStateException("FWD_FRM deserializations should be special-cased pre-4.0");
+ default:
+ throw new AssertionError("Unexpected size " + size);
}
}
- public InetAddressAndPort pre40DeserializeWithLength(DataInputPlus in, int version, int length) throws IOException
- {
- assert length == 4 || length == 16 : "unexpected length " + length;
- byte[] from = new byte[length];
- in.readFully(from, 0, length);
- return InetAddressAndPort.getByAddress(from);
- }
}
}
diff --git a/src/java/org/apache/cassandra/net/ForwardingInfo.java b/src/java/org/apache/cassandra/net/ForwardingInfo.java
index 2ee199a249..7a117bd999 100644
--- a/src/java/org/apache/cassandra/net/ForwardingInfo.java
+++ b/src/java/org/apache/cassandra/net/ForwardingInfo.java
@@ -18,8 +18,6 @@
package org.apache.cassandra.net;
import com.google.common.base.Preconditions;
-import com.google.common.primitives.Ints;
-import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
@@ -39,7 +37,6 @@ import static org.apache.cassandra.utils.vint.VIntCoding.computeUnsignedVIntSize
* A container used to store a node -> message_id map for inter-DC write forwarding.
* We pick one node in each external DC to forward the message to its local peers.
*
- * TODO: in the next protocol version only serialize peers, message id will become redundant once 3.0 is out of the picture
*/
public final class ForwardingInfo implements Serializable
{
@@ -53,19 +50,6 @@ public final class ForwardingInfo implements Serializable
this.messageIds = messageIds;
}
- /**
- * @return {@code true} if all host are to use the same message id, {@code false} otherwise. Starting with 4.0 and
- * above, we should be reusing the same id, always, but it won't always be true until 3.0/3.11 are phased out.
- */
- public boolean useSameMessageID(long id)
- {
- for (int i = 0; i < messageIds.length; i++)
- if (id != messageIds[i])
- return false;
-
- return true;
- }
-
/**
* Apply the provided consumer to all (host, message_id) pairs.
*/
@@ -79,37 +63,33 @@ public final class ForwardingInfo implements Serializable
{
public void serialize(ForwardingInfo forwardTo, DataOutputPlus out, int version) throws IOException
{
+ assert version >= VERSION_40;
long[] ids = forwardTo.messageIds;
List targets = forwardTo.targets;
int count = ids.length;
- if (version >= VERSION_40)
- out.writeUnsignedVInt32(count);
- else
- out.writeInt(count);
+ out.writeUnsignedVInt32(count);
for (int i = 0; i < count; i++)
{
inetAddressAndPortSerializer.serialize(targets.get(i), out, version);
- if (version >= VERSION_40)
- out.writeUnsignedVInt(ids[i]);
- else
- out.writeInt(Ints.checkedCast(ids[i]));
+ out.writeUnsignedVInt(ids[i]);
}
}
public long serializedSize(ForwardingInfo forwardTo, int version)
{
+ assert version >= VERSION_40;
long[] ids = forwardTo.messageIds;
List targets = forwardTo.targets;
int count = ids.length;
- long size = version >= VERSION_40 ? computeUnsignedVIntSize(count) : TypeSizes.sizeof(count);
+ long size = computeUnsignedVIntSize(count);
for (int i = 0; i < count; i++)
{
size += inetAddressAndPortSerializer.serializedSize(targets.get(i), version);
- size += version >= VERSION_40 ? computeUnsignedVIntSize(ids[i]) : 4;
+ size += computeUnsignedVIntSize(ids[i]);
}
return size;
@@ -117,7 +97,8 @@ public final class ForwardingInfo implements Serializable
public ForwardingInfo deserialize(DataInputPlus in, int version) throws IOException
{
- int count = version >= VERSION_40 ? in.readUnsignedVInt32() : in.readInt();
+ assert version >= VERSION_40;
+ int count = in.readUnsignedVInt32();
long[] ids = new long[count];
List targets = new ArrayList<>(count);
@@ -125,7 +106,7 @@ public final class ForwardingInfo implements Serializable
for (int i = 0; i < count; i++)
{
targets.add(inetAddressAndPortSerializer.deserialize(in, version));
- ids[i] = version >= VERSION_40 ? in.readUnsignedVInt32() : in.readInt();
+ ids[i] = in.readUnsignedVInt32();
}
return new ForwardingInfo(targets, ids);
diff --git a/src/java/org/apache/cassandra/net/FrameDecoder.java b/src/java/org/apache/cassandra/net/FrameDecoder.java
index 4cfbf6d6ed..553973f53b 100644
--- a/src/java/org/apache/cassandra/net/FrameDecoder.java
+++ b/src/java/org/apache/cassandra/net/FrameDecoder.java
@@ -51,10 +51,6 @@ import static org.apache.cassandra.utils.ByteBufferUtil.copyBytes;
LZ4 compression with custom frame format; payload is protected by CRC32
* 3. {@link FrameDecoderUnprotected}:
no compression; no integrity protection
- * 4. {@link FrameDecoderLegacy}:
- no compression; no integrity protection; turns unframed streams of legacy messages (< 4.0) into frames
- * 5. {@link FrameDecoderLegacyLZ4}
- * LZ4 compression using standard LZ4 frame format; groups legacy messages (< 4.0) into frames
*/
public abstract class FrameDecoder extends ChannelInboundHandlerAdapter
{
@@ -276,10 +272,6 @@ public abstract class FrameDecoder extends ChannelInboundHandlerAdapter
allocator.putUnusedPortion(buf);
channelRead(ShareableBytes.wrap(buf));
}
- else if (msg instanceof ShareableBytes) // legacy LZ4 decoder
- {
- channelRead((ShareableBytes) msg);
- }
else
{
throw new IllegalArgumentException();
diff --git a/src/java/org/apache/cassandra/net/FrameDecoderLegacy.java b/src/java/org/apache/cassandra/net/FrameDecoderLegacy.java
deleted file mode 100644
index a3d7bc593e..0000000000
--- a/src/java/org/apache/cassandra/net/FrameDecoderLegacy.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.net;
-
-import java.nio.ByteBuffer;
-import java.util.Collection;
-
-import io.netty.channel.ChannelPipeline;
-
-import static java.lang.Math.max;
-import static org.apache.cassandra.net.OutboundConnections.LARGE_MESSAGE_THRESHOLD;
-
-/**
- * {@link InboundMessageHandler} operates on frames that adhere to a certain contract
- * (see {@link FrameDecoder.IntactFrame} and {@link FrameDecoder.CorruptFrame} javadoc).
- *
- * Legacy (pre-4.0) messaging protocol does not natively support framing, however. The job
- * of {@link FrameDecoderLegacy} is turn a raw stream of messages, serialized back to back,
- * into a sequence of frames that adhere to 4.0+ conventions.
- */
-class FrameDecoderLegacy extends FrameDecoder
-{
- private final int messagingVersion;
-
- private int remainingBytesInLargeMessage = 0;
-
- FrameDecoderLegacy(BufferPoolAllocator allocator, int messagingVersion)
- {
- super(allocator);
- this.messagingVersion = messagingVersion;
- }
-
- final void decode(Collection into, ShareableBytes newBytes)
- {
- ByteBuffer in = newBytes.get();
- try
- {
- if (stash != null)
- {
- int length = Message.serializer.inferMessageSize(stash, 0, stash.position(), messagingVersion);
- while (length < 0)
- {
- if (!in.hasRemaining())
- return;
-
- if (stash.position() == stash.capacity())
- stash = ensureCapacity(stash, stash.capacity() * 2);
- copyToSize(in, stash, stash.capacity());
-
- length = Message.serializer.inferMessageSize(stash, 0, stash.position(), messagingVersion);
- if (length >= 0 && length < stash.position())
- {
- int excess = stash.position() - length;
- in.position(in.position() - excess);
- stash.position(length);
- }
- }
-
- final boolean isSelfContained;
- if (length <= LARGE_MESSAGE_THRESHOLD)
- {
- isSelfContained = true;
-
- if (length > stash.capacity())
- stash = ensureCapacity(stash, length);
-
- stash.limit(length);
- allocator.putUnusedPortion(stash); // we may be over capacity from earlier doubling
- if (!copyToSize(in, stash, length))
- return;
- }
- else
- {
- isSelfContained = false;
- remainingBytesInLargeMessage = length - stash.position();
-
- stash.limit(stash.position());
- allocator.putUnusedPortion(stash);
- }
-
- stash.flip();
- assert !isSelfContained || stash.limit() == length;
- ShareableBytes stashed = ShareableBytes.wrap(stash);
- into.add(new IntactFrame(isSelfContained, stashed));
- stash = null;
- }
-
- if (remainingBytesInLargeMessage > 0)
- {
- if (remainingBytesInLargeMessage >= newBytes.remaining())
- {
- remainingBytesInLargeMessage -= newBytes.remaining();
- into.add(new IntactFrame(false, newBytes.sliceAndConsume(newBytes.remaining())));
- return;
- }
- else
- {
- Frame frame = new IntactFrame(false, newBytes.sliceAndConsume(remainingBytesInLargeMessage));
- remainingBytesInLargeMessage = 0;
- into.add(frame);
- }
- }
-
- // we loop incrementing our end pointer until we have no more complete messages,
- // at which point we slice the complete messages, and stash the remainder
- int begin = in.position();
- int end = begin;
- int limit = in.limit();
-
- if (begin == limit)
- return;
-
- while (true)
- {
- int length = Message.serializer.inferMessageSize(in, end, limit, messagingVersion);
-
- if (length >= 0)
- {
- if (end + length <= limit)
- {
- // we have a complete message, so just bump our end pointer
- end += length;
-
- // if we have more bytes, continue to look for another message
- if (end < limit)
- continue;
-
- // otherwise reset length, as we have accounted for it in end
- length = 0;
- }
- }
-
- // we are done; if we have found any complete messages, slice them all into a single frame
- if (begin < end)
- into.add(new IntactFrame(true, newBytes.slice(begin, end)));
-
- // now consider stashing anything leftover
- if (length < 0)
- {
- stash(newBytes, max(64, limit - end), end, limit - end);
- }
- else if (length > LARGE_MESSAGE_THRESHOLD)
- {
- remainingBytesInLargeMessage = length - (limit - end);
- Frame frame = new IntactFrame(false, newBytes.slice(end, limit));
- into.add(frame);
- }
- else if (length > 0)
- {
- stash(newBytes, length, end, limit - end);
- }
- break;
- }
- }
- catch (Message.InvalidLegacyProtocolMagic e)
- {
- into.add(CorruptFrame.unrecoverable(e.read, Message.PROTOCOL_MAGIC));
- }
- finally
- {
- newBytes.release();
- }
- }
-
- void addLastTo(ChannelPipeline pipeline)
- {
- pipeline.addLast("frameDecoderNone", this);
- }
-}
diff --git a/src/java/org/apache/cassandra/net/FrameDecoderLegacyLZ4.java b/src/java/org/apache/cassandra/net/FrameDecoderLegacyLZ4.java
deleted file mode 100644
index 4c620c7b0d..0000000000
--- a/src/java/org/apache/cassandra/net/FrameDecoderLegacyLZ4.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.net;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayDeque;
-import java.util.Collection;
-import java.util.Deque;
-
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.channel.ChannelPipeline;
-import io.netty.handler.codec.compression.Lz4FrameDecoder;
-import net.jpountz.lz4.LZ4Factory;
-import net.jpountz.lz4.LZ4SafeDecompressor;
-import net.jpountz.xxhash.XXHash32;
-import net.jpountz.xxhash.XXHashFactory;
-import org.apache.cassandra.utils.memory.BufferPool;
-import org.apache.cassandra.utils.memory.BufferPools;
-
-import static java.lang.Integer.reverseBytes;
-import static java.lang.String.format;
-import static org.apache.cassandra.net.LegacyLZ4Constants.*;
-import static org.apache.cassandra.utils.ByteBufferUtil.copyBytes;
-
-/**
- * A {@link FrameDecoder} consisting of two chained handlers:
- * 1. A legacy LZ4 block decoder, described below in the description of {@link LZ4Decoder}, followed by
- * 2. An instance of {@link FrameDecoderLegacy} - transforming the raw messages in the uncompressed stream
- * into properly formed frames expected by {@link InboundMessageHandler}
- */
-class FrameDecoderLegacyLZ4 extends FrameDecoderLegacy
-{
- private static final BufferPool bufferPool = BufferPools.forNetworking();
-
- FrameDecoderLegacyLZ4(BufferPoolAllocator allocator, int messagingVersion)
- {
- super(allocator, messagingVersion);
- }
-
- @Override
- void addLastTo(ChannelPipeline pipeline)
- {
- pipeline.addLast("legacyLZ4Decoder", new LZ4Decoder(allocator));
- pipeline.addLast("frameDecoderNone", this);
- }
-
- /**
- * An implementation of LZ4 decoder, used for legacy (3.0, 3.11) connections.
- *
- * Netty's provided implementation - {@link Lz4FrameDecoder} couldn't be reused for
- * two reasons:
- * 1. It has very poor performance when coupled with xxHash, which we use for legacy connections -
- * allocating a single-byte array and making a JNI call for every byte of the payload
- * 2. It was tricky to efficiently integrate with upstream {@link FrameDecoder}, and impossible
- * to make it play nicely with flow control - Netty's implementation, based on
- * {@link io.netty.handler.codec.ByteToMessageDecoder}, would potentially keep triggering
- * reads on its own volition for as long as its last read had no completed frames to supply
- * - defying our goal to only ever trigger channel reads when explicitly requested
- *
- * Since the original LZ4 block format does not contains size of compressed block and size of original data
- * this encoder uses format like LZ4 Java library
- * written by Adrien Grand and approved by Yann Collet (author of original LZ4 library), as implemented by
- * Netty's {@link Lz4FrameDecoder}, but adapted for our interaction model.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + Magic +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |T| Compressed Length
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Uncompressed Length
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | xxHash32 of Uncompressed Payload
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * +-+ +
- * | |
- * + Payload +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- private static class LZ4Decoder extends ChannelInboundHandlerAdapter
- {
- private static final XXHash32 xxhash =
- XXHashFactory.fastestInstance().hash32();
-
- private static final LZ4SafeDecompressor decompressor =
- LZ4Factory.fastestInstance().safeDecompressor();
-
- private final BufferPoolAllocator allocator;
-
- LZ4Decoder(BufferPoolAllocator allocator)
- {
- this.allocator = allocator;
- }
-
- private final Deque frames = new ArrayDeque<>(4);
-
- // total # of frames decoded between two subsequent invocations of channelReadComplete()
- private int decodedFrameCount = 0;
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws CorruptLZ4Frame
- {
- assert msg instanceof BufferPoolAllocator.Wrapped;
- ByteBuffer buf = ((BufferPoolAllocator.Wrapped) msg).adopt();
- // netty will probably have mis-predicted the space needed
- bufferPool.putUnusedPortion(buf);
-
- CorruptLZ4Frame error = null;
- try
- {
- decode(frames, ShareableBytes.wrap(buf));
- }
- catch (CorruptLZ4Frame e)
- {
- error = e;
- }
- finally
- {
- decodedFrameCount += frames.size();
- while (!frames.isEmpty())
- ctx.fireChannelRead(frames.poll());
- }
-
- if (null != error)
- throw error;
- }
-
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx)
- {
- /*
- * If no frames have been decoded from the entire batch of channelRead() calls,
- * then we must trigger another channel read explicitly, or else risk stalling
- * forever without bytes to complete the current in-flight frame.
- */
- if (null != stash && decodedFrameCount == 0 && !ctx.channel().config().isAutoRead())
- ctx.read();
-
- decodedFrameCount = 0;
- ctx.fireChannelReadComplete();
- }
-
- private void decode(Collection into, ShareableBytes newBytes) throws CorruptLZ4Frame
- {
- try
- {
- doDecode(into, newBytes);
- }
- finally
- {
- newBytes.release();
- }
- }
-
- private void doDecode(Collection into, ShareableBytes newBytes) throws CorruptLZ4Frame
- {
- ByteBuffer in = newBytes.get();
-
- if (null != stash)
- {
- if (!copyToSize(in, stash, HEADER_LENGTH))
- return;
-
- header.read(stash, 0);
- header.validate();
-
- int frameLength = header.frameLength();
- stash = ensureCapacity(stash, frameLength);
-
- if (!copyToSize(in, stash, frameLength))
- return;
-
- stash.flip();
- ShareableBytes stashed = ShareableBytes.wrap(stash);
- stash = null;
-
- try
- {
- into.add(decompressFrame(stashed, 0, frameLength, header));
- }
- finally
- {
- stashed.release();
- }
- }
-
- int begin = in.position();
- int limit = in.limit();
- while (begin < limit)
- {
- int remaining = limit - begin;
- if (remaining < HEADER_LENGTH)
- {
- stash(newBytes, HEADER_LENGTH, begin, remaining);
- return;
- }
-
- header.read(in, begin);
- header.validate();
-
- int frameLength = header.frameLength();
- if (remaining < frameLength)
- {
- stash(newBytes, frameLength, begin, remaining);
- return;
- }
-
- into.add(decompressFrame(newBytes, begin, begin + frameLength, header));
- begin += frameLength;
- }
- }
-
- private ShareableBytes decompressFrame(ShareableBytes bytes, int begin, int end, Header header) throws CorruptLZ4Frame
- {
- ByteBuffer buf = bytes.get();
-
- if (header.uncompressedLength == 0)
- return bytes.slice(begin + HEADER_LENGTH, end);
-
- if (!header.isCompressed())
- {
- validateChecksum(buf, begin + HEADER_LENGTH, header);
- return bytes.slice(begin + HEADER_LENGTH, end);
- }
-
- ByteBuffer out = allocator.get(header.uncompressedLength);
- try
- {
- int sourceLength = end - (begin + HEADER_LENGTH);
- decompressor.decompress(buf, begin + HEADER_LENGTH, sourceLength, out, 0, header.uncompressedLength);
- validateChecksum(out, 0, header);
- return ShareableBytes.wrap(out);
- }
- catch (Throwable t)
- {
- bufferPool.put(out);
- throw t;
- }
- }
-
- private void validateChecksum(ByteBuffer buf, int begin, Header header) throws CorruptLZ4Frame
- {
- int checksum = xxhash.hash(buf, begin, header.uncompressedLength, XXHASH_SEED) & XXHASH_MASK;
- if (checksum != header.checksum)
- except("Invalid checksum detected: %d (expected: %d)", checksum, header.checksum);
- }
-
- @Override
- public void channelInactive(ChannelHandlerContext ctx)
- {
- if (null != stash)
- {
- bufferPool.put(stash);
- stash = null;
- }
-
- while (!frames.isEmpty())
- frames.poll().release();
-
- ctx.fireChannelInactive();
- }
-
- /* reusable container for deserialized header fields */
- private static final class Header
- {
- long magicNumber;
- byte token;
- int compressedLength;
- int uncompressedLength;
- int checksum;
-
- int frameLength()
- {
- return HEADER_LENGTH + compressedLength;
- }
-
- boolean isCompressed()
- {
- return (token & 0xF0) == 0x20;
- }
-
- int maxUncompressedLength()
- {
- return 1 << ((token & 0x0F) + 10);
- }
-
- void read(ByteBuffer in, int begin)
- {
- magicNumber = in.getLong(begin + MAGIC_NUMBER_OFFSET );
- token = in.get (begin + TOKEN_OFFSET );
- compressedLength = reverseBytes(in.getInt (begin + COMPRESSED_LENGTH_OFFSET ));
- uncompressedLength = reverseBytes(in.getInt (begin + UNCOMPRESSED_LENGTH_OFFSET));
- checksum = reverseBytes(in.getInt (begin + CHECKSUM_OFFSET ));
- }
-
- void validate() throws CorruptLZ4Frame
- {
- if (magicNumber != MAGIC_NUMBER)
- except("Invalid magic number at the beginning of an LZ4 block: %d", magicNumber);
-
- int blockType = token & 0xF0;
- if (!(blockType == BLOCK_TYPE_COMPRESSED || blockType == BLOCK_TYPE_NON_COMPRESSED))
- except("Invalid block type encountered: %d", blockType);
-
- if (compressedLength < 0 || compressedLength > MAX_BLOCK_LENGTH)
- except("Invalid compressedLength: %d (expected: 0-%d)", compressedLength, MAX_BLOCK_LENGTH);
-
- if (uncompressedLength < 0 || uncompressedLength > maxUncompressedLength())
- except("Invalid uncompressedLength: %d (expected: 0-%d)", uncompressedLength, maxUncompressedLength());
-
- if ( uncompressedLength == 0 && compressedLength != 0
- || uncompressedLength != 0 && compressedLength == 0
- || !isCompressed() && uncompressedLength != compressedLength)
- {
- except("Stream corrupted: compressedLength(%d) and decompressedLength(%d) mismatch", compressedLength, uncompressedLength);
- }
- }
- }
- private final Header header = new Header();
-
- /**
- * @return {@code in} if has sufficient capacity, otherwise a replacement from {@code BufferPool} that {@code in} is copied into
- */
- private ByteBuffer ensureCapacity(ByteBuffer in, int capacity)
- {
- if (in.capacity() >= capacity)
- return in;
-
- ByteBuffer out = allocator.getAtLeast(capacity);
- in.flip();
- out.put(in);
- bufferPool.put(in);
- return out;
- }
-
- private ByteBuffer stash;
-
- private void stash(ShareableBytes in, int stashLength, int begin, int length)
- {
- ByteBuffer out = allocator.getAtLeast(stashLength);
- copyBytes(in.get(), begin, out, 0, length);
- out.position(length);
- stash = out;
- }
-
- static final class CorruptLZ4Frame extends IOException
- {
- CorruptLZ4Frame(String message)
- {
- super(message);
- }
- }
-
- private static void except(String format, Object... args) throws CorruptLZ4Frame
- {
- throw new CorruptLZ4Frame(format(format, args));
- }
- }
-}
diff --git a/src/java/org/apache/cassandra/net/FrameEncoderLegacy.java b/src/java/org/apache/cassandra/net/FrameEncoderLegacy.java
deleted file mode 100644
index 8bfd2678ad..0000000000
--- a/src/java/org/apache/cassandra/net/FrameEncoderLegacy.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.net;
-
-import java.nio.ByteBuffer;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandler;
-
-/**
- * A no-op frame encoder: legacy format doesn't support framing. Instead, the byte stream
- * contains messages, serialized back to back.
- */
-@ChannelHandler.Sharable
-class FrameEncoderLegacy extends FrameEncoder
-{
- static final FrameEncoderLegacy instance = new FrameEncoderLegacy();
-
- ByteBuf encode(boolean isSelfContained, ByteBuffer buffer)
- {
- return GlobalBufferPoolAllocator.wrap(buffer);
- }
-}
diff --git a/src/java/org/apache/cassandra/net/FrameEncoderLegacyLZ4.java b/src/java/org/apache/cassandra/net/FrameEncoderLegacyLZ4.java
deleted file mode 100644
index fd8b36b85e..0000000000
--- a/src/java/org/apache/cassandra/net/FrameEncoderLegacyLZ4.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.net;
-
-import java.nio.ByteBuffer;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandler;
-import net.jpountz.lz4.LZ4Compressor;
-import net.jpountz.lz4.LZ4Factory;
-import net.jpountz.xxhash.XXHash32;
-import net.jpountz.xxhash.XXHashFactory;
-import org.apache.cassandra.io.compress.BufferType;
-import org.apache.cassandra.utils.ByteBufferUtil;
-
-import static java.lang.Integer.reverseBytes;
-import static java.lang.Math.min;
-import static org.apache.cassandra.net.LegacyLZ4Constants.*;
-
-/**
- * LZ4 {@link FrameEncoder} implementation for compressed legacy (3.0, 3.11) connections.
- *
- * Netty's provided implementation - {@link io.netty.handler.codec.compression.Lz4FrameEncoder} couldn't be reused
- * for two reasons:
- * 1. It notifies flushes as successful when they may not be, by flushing an empty buffer ahead
- * of the compressed buffer
- * 2. It has very poor performance when coupled with xxHash, which we use for legacy connections -
- * allocating a single-byte array and making a JNI call for every byte of the payload
- *
- * Please see {@link FrameDecoderLegacyLZ4} for the description of the on-wire format of the LZ4 blocks
- * used by this encoder.
- */
-@ChannelHandler.Sharable
-class FrameEncoderLegacyLZ4 extends FrameEncoder
-{
- static final FrameEncoderLegacyLZ4 instance =
- new FrameEncoderLegacyLZ4(XXHashFactory.fastestInstance().hash32(),
- LZ4Factory.fastestInstance().fastCompressor());
-
- private final XXHash32 xxhash;
- private final LZ4Compressor compressor;
-
- private FrameEncoderLegacyLZ4(XXHash32 xxhash, LZ4Compressor compressor)
- {
- this.xxhash = xxhash;
- this.compressor = compressor;
- }
-
- @Override
- ByteBuf encode(boolean isSelfContained, ByteBuffer payload)
- {
- ByteBuffer frame = null;
- try
- {
- frame = bufferPool.getAtLeast(calculateMaxFrameLength(payload), BufferType.OFF_HEAP);
-
- int frameOffset = 0;
- int payloadOffset = 0;
-
- int payloadLength = payload.remaining();
- while (payloadOffset < payloadLength)
- {
- int blockLength = min(DEFAULT_BLOCK_LENGTH, payloadLength - payloadOffset);
- frameOffset += compressBlock(frame, frameOffset, payload, payloadOffset, blockLength);
- payloadOffset += blockLength;
- }
-
- frame.limit(frameOffset);
- bufferPool.putUnusedPortion(frame);
-
- return GlobalBufferPoolAllocator.wrap(frame);
- }
- catch (Throwable t)
- {
- if (null != frame)
- bufferPool.put(frame);
- throw t;
- }
- finally
- {
- bufferPool.put(payload);
- }
- }
-
- private int compressBlock(ByteBuffer frame, int frameOffset, ByteBuffer payload, int payloadOffset, int blockLength)
- {
- int frameBytesRemaining = frame.limit() - (frameOffset + HEADER_LENGTH);
- int compressedLength = compressor.compress(payload, payloadOffset, blockLength, frame, frameOffset + HEADER_LENGTH, frameBytesRemaining);
- if (compressedLength >= blockLength)
- {
- ByteBufferUtil.copyBytes(payload, payloadOffset, frame, frameOffset + HEADER_LENGTH, blockLength);
- compressedLength = blockLength;
- }
- int checksum = xxhash.hash(payload, payloadOffset, blockLength, XXHASH_SEED) & XXHASH_MASK;
- writeHeader(frame, frameOffset, compressedLength, blockLength, checksum);
- return HEADER_LENGTH + compressedLength;
- }
-
- private static final byte TOKEN_NON_COMPRESSED = 0x15;
- private static final byte TOKEN_COMPRESSED = 0x25;
-
- private static void writeHeader(ByteBuffer frame, int frameOffset, int compressedLength, int uncompressedLength, int checksum)
- {
- byte token = compressedLength == uncompressedLength
- ? TOKEN_NON_COMPRESSED
- : TOKEN_COMPRESSED;
-
- frame.putLong(frameOffset + MAGIC_NUMBER_OFFSET, MAGIC_NUMBER );
- frame.put (frameOffset + TOKEN_OFFSET, token );
- frame.putInt (frameOffset + COMPRESSED_LENGTH_OFFSET, reverseBytes(compressedLength) );
- frame.putInt (frameOffset + UNCOMPRESSED_LENGTH_OFFSET, reverseBytes(uncompressedLength));
- frame.putInt (frameOffset + CHECKSUM_OFFSET, reverseBytes(checksum) );
- }
-
- private int calculateMaxFrameLength(ByteBuffer payload)
- {
- int payloadLength = payload.remaining();
- int blockCount = payloadLength / DEFAULT_BLOCK_LENGTH + (payloadLength % DEFAULT_BLOCK_LENGTH != 0 ? 1 : 0);
- return compressor.maxCompressedLength(payloadLength) + HEADER_LENGTH * blockCount;
- }
-}
diff --git a/src/java/org/apache/cassandra/net/HandshakeProtocol.java b/src/java/org/apache/cassandra/net/HandshakeProtocol.java
index a82c1152e1..3217aeae8a 100644
--- a/src/java/org/apache/cassandra/net/HandshakeProtocol.java
+++ b/src/java/org/apache/cassandra/net/HandshakeProtocol.java
@@ -22,21 +22,17 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
-import com.google.common.annotations.VisibleForTesting;
-
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.io.compress.BufferType;
import org.apache.cassandra.io.util.DataInputBuffer;
-import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputBufferFixed;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.utils.memory.BufferPools;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.apache.cassandra.locator.InetAddressAndPort.Serializer.inetAddressAndPortSerializer;
-import static org.apache.cassandra.net.MessagingService.VERSION_30;
import static org.apache.cassandra.net.MessagingService.VERSION_40;
import static org.apache.cassandra.net.Message.validateLegacyProtocolMagic;
import static org.apache.cassandra.net.Crc.*;
@@ -52,8 +48,7 @@ import static org.apache.cassandra.net.OutboundConnectionSettings.*;
* it will simply disconnect and reconnect with a more appropriate version. But if the version is acceptable, the connection
* initiator sends the third message of the protocol, after which it considers the connection ready.
*/
-@VisibleForTesting
-public class HandshakeProtocol
+class HandshakeProtocol
{
static final long TIMEOUT_MILLIS = 3 * DatabaseDescriptor.getRpcTimeout(MILLISECONDS);
@@ -94,8 +89,6 @@ public class HandshakeProtocol
private static final int MIN_LENGTH = 8;
private static final int MAX_LENGTH = 12 + InetAddressAndPort.Serializer.MAXIMUM_SIZE;
- @Deprecated // this is ignored by post40 nodes, i.e. if maxMessagingVersion is set
- final int requestMessagingVersion;
// the messagingVersion bounds the sender will accept to initiate a connection;
// if the remote peer supports any, the newest supported version will be selected; otherwise the nearest supported version
final AcceptVersions acceptVersions;
@@ -103,17 +96,15 @@ public class HandshakeProtocol
final Framing framing;
final InetAddressAndPort from;
- Initiate(int requestMessagingVersion, AcceptVersions acceptVersions, ConnectionType type, Framing framing, InetAddressAndPort from)
+ Initiate(AcceptVersions acceptVersions, ConnectionType type, Framing framing, InetAddressAndPort from)
{
- this.requestMessagingVersion = requestMessagingVersion;
this.acceptVersions = acceptVersions;
this.type = type;
this.framing = framing;
this.from = from;
}
- @VisibleForTesting
- int encodeFlags()
+ private int encodeFlags()
{
int flags = 0;
if (type.isMessaging())
@@ -123,11 +114,7 @@ public class HandshakeProtocol
// framing id is split over 2nd and 4th bits, for backwards compatibility
flags |= ((framing.id & 1) << 2) | ((framing.id & 2) << 3);
- flags |= (requestMessagingVersion << 8);
-
- if (requestMessagingVersion < VERSION_40 || acceptVersions.max < VERSION_40)
- return flags; // for testing, permit serializing as though we are pre40
-
+ flags |= (acceptVersions.min << 8); // legacy (pre40)
flags |= (acceptVersions.min << 16);
flags |= (acceptVersions.max << 24);
return flags;
@@ -140,12 +127,8 @@ public class HandshakeProtocol
{
out.writeInt(Message.PROTOCOL_MAGIC);
out.writeInt(encodeFlags());
-
- if (requestMessagingVersion >= VERSION_40 && acceptVersions.max >= VERSION_40)
- {
- inetAddressAndPortSerializer.serialize(from, out, requestMessagingVersion);
- out.writeInt(computeCrc32(buffer, 0, buffer.position()));
- }
+ inetAddressAndPortSerializer.serialize(from, out, acceptVersions.min);
+ out.writeInt(computeCrc32(buffer, 0, buffer.position()));
buffer.flip();
return GlobalBufferPoolAllocator.wrap(buffer);
}
@@ -167,9 +150,17 @@ public class HandshakeProtocol
validateLegacyProtocolMagic(in.readInt());
int flags = in.readInt();
- int requestedMessagingVersion = getBits(flags, 8, 8);
+ // legacy pre40 messagingVersion flag
+ if (getBits(flags, 8, 8) < VERSION_40)
+ return null;
+
int minMessagingVersion = getBits(flags, 16, 8);
int maxMessagingVersion = getBits(flags, 24, 8);
+
+ // 5.0+ does not support pre40
+ if (maxMessagingVersion < MessagingService.VERSION_40)
+ return null;
+
int framingBits = getBits(flags, 2, 1) | (getBits(flags, 4, 1) << 1);
Framing framing = Framing.forId(framingBits);
@@ -179,23 +170,15 @@ public class HandshakeProtocol
? ConnectionType.STREAMING
: ConnectionType.fromId(getBits(flags, 0, 2));
- InetAddressAndPort from = null;
+ InetAddressAndPort from = inetAddressAndPortSerializer.deserialize(in, minMessagingVersion);
- if (requestedMessagingVersion >= VERSION_40 && maxMessagingVersion >= MessagingService.VERSION_40)
- {
- from = inetAddressAndPortSerializer.deserialize(in, requestedMessagingVersion);
-
- int computed = computeCrc32(nio, start, nio.position());
- int read = in.readInt();
- if (read != computed)
- throw new InvalidCrc(read, computed);
- }
+ int computed = computeCrc32(nio, start, nio.position());
+ int read = in.readInt();
+ if (read != computed)
+ throw new InvalidCrc(read, computed);
buf.skipBytes(nio.position() - start);
- return new Initiate(requestedMessagingVersion,
- minMessagingVersion == 0 && maxMessagingVersion == 0
- ? null : new AcceptVersions(minMessagingVersion, maxMessagingVersion),
- type, framing, from);
+ return new Initiate(new AcceptVersions(minMessagingVersion, maxMessagingVersion), type, framing, from);
}
catch (EOFException e)
@@ -204,7 +187,6 @@ public class HandshakeProtocol
}
}
- @VisibleForTesting
@Override
public boolean equals(Object other)
{
@@ -214,17 +196,15 @@ public class HandshakeProtocol
Initiate that = (Initiate)other;
return this.type == that.type
&& this.framing == that.framing
- && this.requestMessagingVersion == that.requestMessagingVersion
&& Objects.equals(this.acceptVersions, that.acceptVersions);
}
@Override
public String toString()
{
- return String.format("Initiate(request: %d, min: %d, max: %d, type: %s, framing: %b, from: %s)",
- requestMessagingVersion,
- acceptVersions == null ? requestMessagingVersion : acceptVersions.min,
- acceptVersions == null ? requestMessagingVersion : acceptVersions.max,
+ return String.format("Initiate(min: %d, max: %d, type: %s, framing: %b, from: %s)",
+ acceptVersions.min,
+ acceptVersions.max,
type, framing, from);
}
}
@@ -238,9 +218,8 @@ public class HandshakeProtocol
* 1) the messaging version of the peer sending this message
* 2) the negotiated messaging version if one could be accepted by both peers,
* or if not the closest version that this peer could support to the ones requested
- * 3) a CRC protectingn the integrity of the message
+ * 3) a CRC protecting the integrity of the message
*
- * Note that the pre40 equivalent of this message contains ONLY the messaging version of the peer.
*/
static class Accept
{
@@ -266,18 +245,7 @@ public class HandshakeProtocol
return buffer;
}
- /**
- * Respond to pre40 nodes only with our current messagingVersion
- */
- static ByteBuf respondPre40(int messagingVersion, ByteBufAllocator allocator)
- {
- ByteBuf buffer = allocator.directBuffer(4);
- buffer.clear();
- buffer.writeInt(messagingVersion);
- return buffer;
- }
-
- static Accept maybeDecode(ByteBuf in, int handshakeMessagingVersion) throws InvalidCrc
+ static Accept maybeDecode(ByteBuf in) throws InvalidCrc
{
int readerIndex = in.readerIndex();
if (in.readableBytes() < 4)
@@ -285,9 +253,9 @@ public class HandshakeProtocol
int maxMessagingVersion = in.readInt();
int useMessagingVersion = 0;
- // if the other node is pre-4.0, it will respond only with its maxMessagingVersion
- if (maxMessagingVersion < VERSION_40 || handshakeMessagingVersion < VERSION_40)
- return new Accept(useMessagingVersion, maxMessagingVersion);
+ // pre-4.0 not supported, close the connection
+ if (maxMessagingVersion < VERSION_40)
+ return null;
if (in.readableBytes() < 8)
{
@@ -305,7 +273,6 @@ public class HandshakeProtocol
return new Accept(useMessagingVersion, maxMessagingVersion);
}
- @VisibleForTesting
@Override
public boolean equals(Object other)
{
@@ -321,91 +288,6 @@ public class HandshakeProtocol
}
}
- /**
- * The third message of the handshake, sent by pre40 nodes on reception of {@link Accept}.
- * This message contains:
- * 1) The connection initiator's {@link org.apache.cassandra.net.MessagingService#current_version} (4 bytes).
- * This indicates the max messaging version supported by this node.
- * 2) The connection initiator's broadcast address as encoded by {@link InetAddressAndPort.Serializer}.
- * This can be either 7 bytes for an IPv4 address, or 19 bytes for an IPv6 one, post40.
- * This can be either 5 bytes for an IPv4 address, or 17 bytes for an IPv6 one, pre40.
- *
- * This message concludes the legacy handshake protocol.
- */
- static class ConfirmOutboundPre40
- {
- private static final int MAX_LENGTH = 4 + InetAddressAndPort.Serializer.MAXIMUM_SIZE;
-
- final int maxMessagingVersion;
- final InetAddressAndPort from;
-
- ConfirmOutboundPre40(int maxMessagingVersion, InetAddressAndPort from)
- {
- this.maxMessagingVersion = maxMessagingVersion;
- this.from = from;
- }
-
- ByteBuf encode()
- {
- ByteBuffer buffer = BufferPools.forNetworking().get(MAX_LENGTH, BufferType.OFF_HEAP);
- try (DataOutputBufferFixed out = new DataOutputBufferFixed(buffer))
- {
- out.writeInt(maxMessagingVersion);
- // pre-4.0 nodes should only receive the address, never port, and it's ok to hardcode VERSION_30
- inetAddressAndPortSerializer.serialize(from, out, VERSION_30);
- buffer.flip();
- return GlobalBufferPoolAllocator.wrap(buffer);
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- @SuppressWarnings("resource")
- static ConfirmOutboundPre40 maybeDecode(ByteBuf in)
- {
- ByteBuffer nio = in.nioBuffer();
- int start = nio.position();
- DataInputPlus input = new DataInputBuffer(nio, false);
- try
- {
- int version = input.readInt();
- InetAddressAndPort address = inetAddressAndPortSerializer.deserialize(input, version);
- in.skipBytes(nio.position() - start);
- return new ConfirmOutboundPre40(version, address);
- }
- catch (EOFException e)
- {
- // makes the assumption we didn't have enough bytes to deserialize an IPv6 address,
- // as we only check the MIN_LENGTH of the buf.
- return null;
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e);
- }
- }
-
- @VisibleForTesting
- @Override
- public boolean equals(Object other)
- {
- if (!(other instanceof ConfirmOutboundPre40))
- return false;
-
- ConfirmOutboundPre40 that = (ConfirmOutboundPre40) other;
- return this.maxMessagingVersion == that.maxMessagingVersion
- && Objects.equals(this.from, that.from);
- }
-
- @Override
- public String toString()
- {
- return String.format("ConfirmOutboundPre40(maxMessagingVersion: %d; address: %s)", maxMessagingVersion, from);
- }
- }
-
private static int getBits(int packed, int start, int count)
{
return (packed >>> start) & ~(-1 << count);
diff --git a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
index e4de527dfc..b6bd17567c 100644
--- a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
+++ b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
@@ -273,7 +273,6 @@ public class InboundConnectionInitiator
private final InboundConnectionSettings settings;
private HandshakeProtocol.Initiate initiate;
- private HandshakeProtocol.ConfirmOutboundPre40 confirmOutboundPre40;
/**
* A future the essentially places a timeout on how long we'll wait for the peer
@@ -301,7 +300,6 @@ public class InboundConnectionInitiator
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List