Promote protocol v5 from beta

Patch by Sam Tunnicliffe; reviewed by Alex Petrov and Eduard Tudenhoefner
for CASSANDRA-14973
This commit is contained in:
Sam Tunnicliffe 2021-02-22 12:01:36 +00:00
parent f32475a839
commit c9d6c725dd
17 changed files with 75 additions and 50 deletions

View File

@ -1,4 +1,5 @@
4.0-beta5
* Promote protocol V5 out of beta (CASSANDRA-14973)
* Fix incorrect encoding for strings can be UTF8 (CASSANDRA-16429)
* Fix node unable to join when RF > N in multi-DC with added warning (CASSANDRA-16296)
* Add an option to nodetool tablestats to check sstable location correctness (CASSANDRA-16344)

View File

@ -133,7 +133,7 @@ Upgrading
CASSANDRA-16083, backward compatibility layer was added so it can be still exposed under the old 3.11 scope.
- Native protocol v5 is promoted from beta in this release. The wire format has changed
significantly and users should take care to ensure client drivers are upgraded to a version
with support for the final v5 format, if currently connecting over v5-beta. (CASSANDRA-15299)
with support for the final v5 format, if currently connecting over v5-beta. (CASSANDRA-15299, CASSANDRA-14973)
- Cassandra removed support for the OldNetworkTopologyStrategy. Before upgrading you will need to change the
replication strategy for the keyspaces using this strategy to the NetworkTopologyStrategy. (CASSANDRA-13990)
- Sstables for tables using with a frozen UDT written by C* 3.0 appear as corrupted.

View File

@ -476,7 +476,7 @@ class Shell(cmd.Cmd):
if protocol_version is not None:
kwargs['protocol_version'] = protocol_version
else:
kwargs['protocol_version'] = 4
kwargs['protocol_version'] = 5
self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
auth_provider=self.auth_provider,
ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,

View File

@ -645,6 +645,7 @@
</dependency>
<dependency groupId="com.google.code.findbugs" artifactId="jsr305" version="2.0.2" />
<dependency groupId="com.clearspring.analytics" artifactId="stream" version="2.5.2" />
<!-- UPDATE AND UNCOMMENT ON THE DRIVER RELEASE, BEFORE 4.0 RELEASE
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" version="3.10.0" classifier="shaded">
<exclusion groupId="io.netty" artifactId="netty-buffer"/>
<exclusion groupId="io.netty" artifactId="netty-codec"/>
@ -652,6 +653,7 @@
<exclusion groupId="io.netty" artifactId="netty-transport"/>
<exclusion groupId="org.slf4j" artifactId="slf4j-api"/>
</dependency>
-->
<dependency groupId="org.eclipse.jdt.core.compiler" artifactId="ecj" version="${ecj.version}" />
<dependency groupId="org.caffinitas.ohc" artifactId="ohc-core" version="${ohc.version}">
<exclusion groupId="org.slf4j" artifactId="slf4j-api"/>
@ -748,7 +750,9 @@
<dependency groupId="org.apache.hadoop" artifactId="hadoop-minicluster"/>
<dependency groupId="com.google.code.findbugs" artifactId="jsr305"/>
<dependency groupId="org.antlr" artifactId="antlr"/>
<!-- UPDATE AND UNCOMMENT ON THE DRIVER RELEASE, BEFORE 4.0 RELEASE
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" classifier="shaded"/>
-->
<dependency groupId="org.eclipse.jdt.core.compiler" artifactId="ecj"/>
<dependency groupId="org.caffinitas.ohc" artifactId="ohc-core"/>
<dependency groupId="org.caffinitas.ohc" artifactId="ohc-core-j8"/>
@ -779,7 +783,9 @@
<dependency groupId="junit" artifactId="junit"/>
<dependency groupId="org.mockito" artifactId="mockito-core" />
<dependency groupId="org.reflections" artifactId="reflections" />
<!-- UPDATE AND UNCOMMENT ON THE DRIVER RELEASE, BEFORE 4.0 RELEASE
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" classifier="shaded"/>
-->
<dependency groupId="io.netty" artifactId="netty-bom" type="pom" />
<dependency groupId="io.netty" artifactId="netty-all"/>
<dependency groupId="org.eclipse.jdt.core.compiler" artifactId="ecj"/>
@ -856,14 +862,15 @@
<dependency groupId="org.apache.hadoop" artifactId="hadoop-minicluster" optional="true"/>
<!-- don't need the Java Driver to run, but if you use the hadoop stuff or UDFs -->
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" classifier="shaded" optional="true">
<exclusion groupId="io.netty" artifactId="netty-buffer"/>
<exclusion groupId="io.netty" artifactId="netty-codec"/>
<exclusion groupId="io.netty" artifactId="netty-handler"/>
<exclusion groupId="io.netty" artifactId="netty-transport"/>
</dependency>
<!-- don't need jna to run, but nice to have -->
<!-- UPDATE AND UNCOMMENT ON THE DRIVER RELEASE, BEFORE 4.0 RELEASE
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" classifier="shaded" optional="true">
<exclusion groupId="io.netty" artifactId="netty-buffer"/>
<exclusion groupId="io.netty" artifactId="netty-codec"/>
<exclusion groupId="io.netty" artifactId="netty-handler"/>
<exclusion groupId="io.netty" artifactId="netty-transport"/>
</dependency>
-->
<!-- don't need jna to run, but nice to have -->
<dependency groupId="net.java.dev.jna" artifactId="jna"/>
<!-- don't need jamm unless running a server in which case it needs to be a -javagent to be used anyway -->

Binary file not shown.

View File

@ -77,6 +77,7 @@ public final class CodecUtils
case V3:
case V4:
case V5:
case V6:
return input.getInt();
default:
throw new IllegalArgumentException(String.valueOf(version));
@ -107,6 +108,7 @@ public final class CodecUtils
case V3:
case V4:
case V5:
case V6:
output.putInt(size);
break;
default:
@ -149,6 +151,7 @@ public final class CodecUtils
case V3:
case V4:
case V5:
case V6:
if (value == null)
{
output.putInt(-1);
@ -230,6 +233,7 @@ public final class CodecUtils
case V3:
case V4:
case V5:
case V6:
return 4;
default:
throw new IllegalArgumentException(String.valueOf(version));
@ -252,6 +256,7 @@ public final class CodecUtils
case V3:
case V4:
case V5:
case V6:
return value == null ? 4 : 4 + value.remaining();
default:
throw new IllegalArgumentException(String.valueOf(version));

View File

@ -335,10 +335,23 @@ public class CQLMessageHandler<M extends Message> extends AbstractMessageHandler
int messageSize = Ints.checkedCast(header.bodySizeInBytes);
receivedBytes += buf.remaining();
if (throwOnOverload)
LargeMessage largeMessage = new LargeMessage(header);
if (!acquireCapacity(header, endpointReserve, globalReserve))
{
LargeMessage largeMessage = new LargeMessage(header);
if (!acquireCapacity(header, endpointReserve, globalReserve))
// In the case of large messages, never stop processing incoming frames
// as this will halt the client meaning no further frames will be sent,
// leading to starvation.
// If the throwOnOverload option is set, don't process the message once
// read, return an error response to notify the client that resource
// limits have been exceeded. If the option isn't set, the only thing we
// can do is to consume the subsequent frames and process the message.
// Large and small messages are never interleaved for a single client, so
// we know that this client will finish sending the large message before
// anything else. Other clients sending small messages concurrently will
// be backpressured by the global resource limits. The server is still
// vulnerable to overload by multiple clients sending large messages
// concurrently.
if (throwOnOverload)
{
// discard the request and throw an exception
ClientMetrics.instance.markRequestDiscarded();
@ -350,26 +363,12 @@ public class CQLMessageHandler<M extends Message> extends AbstractMessageHandler
globalReserve.using(),
header);
// mark as overloaded so that we consume
// subsequent frames and then discard the message
// mark as overloaded so that discard the message
// after consuming any subsequent frames
largeMessage.markOverloaded();
}
this.largeMessage = largeMessage;
largeMessage.supply(frame);
// Don't stop processing incoming frames, rely on the client to apply
// backpressure when it receives OverloadedException
return true;
}
else
{
if (!acquireCapacityAndQueueOnFailure(header, endpointReserve, globalReserve))
{
receivedBytes += frame.frameSize;
return false;
}
}
largeMessage = new LargeMessage(header);
this.largeMessage = largeMessage;
largeMessage.supply(frame);
return true;
}

View File

@ -213,8 +213,11 @@ public class ClientResourceLimits
public String toString()
{
return String.format("InflightEndpointRequestPayload: %d, InflightOverallRequestPayload: %d",
endpointAndGlobal.endpoint().using(), endpointAndGlobal.global().using());
return String.format("InflightEndpointRequestPayload: %d/%d, InflightOverallRequestPayload: %d/%d",
endpointAndGlobal.endpoint().using(),
endpointAndGlobal.endpoint().limit(),
endpointAndGlobal.global().using(),
endpointAndGlobal.global().limit());
}
}

View File

@ -43,7 +43,8 @@ public enum ProtocolVersion implements Comparable<ProtocolVersion>
V2(2, "v2", false), // no longer supported
V3(3, "v3", false),
V4(4, "v4", false),
V5(5, "v5-beta", true);
V5(5, "v5", false),
V6(6, "v6-beta", true);
/** The version number */
private final int num;
@ -62,7 +63,7 @@ public enum ProtocolVersion implements Comparable<ProtocolVersion>
}
/** The supported versions stored as an array, these should be private and are required for fast decoding*/
private final static ProtocolVersion[] SUPPORTED_VERSIONS = new ProtocolVersion[] { V3, V4, V5 };
private final static ProtocolVersion[] SUPPORTED_VERSIONS = new ProtocolVersion[] { V3, V4, V5, V6 };
final static ProtocolVersion MIN_SUPPORTED_VERSION = SUPPORTED_VERSIONS[0];
final static ProtocolVersion MAX_SUPPORTED_VERSION = SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1];
@ -73,8 +74,8 @@ public enum ProtocolVersion implements Comparable<ProtocolVersion>
public final static EnumSet<ProtocolVersion> UNSUPPORTED = EnumSet.complementOf(SUPPORTED);
/** The preferred versions */
public final static ProtocolVersion CURRENT = V4;
public final static Optional<ProtocolVersion> BETA = Optional.of(V5);
public final static ProtocolVersion CURRENT = V5;
public final static Optional<ProtocolVersion> BETA = Optional.of(V6);
public static List<String> supportedVersions()
{

View File

@ -801,7 +801,7 @@ public class DescribeStatementTest extends CQLTester
// As different ProtocolVersions use different driver instances, we use different ProtocolVersions
// for the with and without "USE keyspace" cases.
ProtocolVersion v = useKs != null ? ProtocolVersion.CURRENT : ProtocolVersion.V5;
ProtocolVersion v = useKs != null ? ProtocolVersion.CURRENT : ProtocolVersion.V6;
if (useKs != null)
executeNet(v, "USE " + useKs);

View File

@ -110,7 +110,7 @@ public class ProtocolBetaVersionTest extends CQLTester
}
catch (Exception e)
{
assertEquals("Beta version of server used (5/v5-beta), but USE_BETA flag is not set",
assertEquals("Beta version of server used (6/v6-beta), but USE_BETA flag is not set",
e.getMessage());
}
}

View File

@ -135,7 +135,7 @@ public class CQLConnectionTest
.matches(message ->
message.error.getMessage()
.equals("Invalid or unsupported protocol version (99); " +
"supported versions are (3/v3, 4/v4, 5/v5-beta)"));
"supported versions are (3/v3, 4/v4, 5/v5, 6/v6-beta)"));
server.stop();
// the failure happens before any capacity is allocated

View File

@ -43,6 +43,7 @@ import static com.datastax.driver.core.ProtocolVersion.V2;
import static com.datastax.driver.core.ProtocolVersion.V3;
import static com.datastax.driver.core.ProtocolVersion.V4;
import static com.datastax.driver.core.ProtocolVersion.V5;
import static com.datastax.driver.core.ProtocolVersion.V6;
import static org.apache.cassandra.transport.messages.StartupMessage.CQL_VERSION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -67,22 +68,23 @@ public class ProtocolNegotiationTest extends CQLTester
}
@Test
public void serverSupportsV3AndV4ByDefault()
public void serverSupportsV3AndV4AndV5ByDefault()
{
// client can explicitly request either V3 or V4
// client can explicitly request either V3, V4 or V5
testConnection(V3, V3);
testConnection(V4, V4);
testConnection(V5, V5);
// if not specified, V4 is the default
testConnection(null, V4);
testConnection(NEWEST_SUPPORTED, V4);
// if not specified, V5 is the default
testConnection(null, V5);
testConnection(NEWEST_SUPPORTED, V5);
}
@Test
public void supportV5ConnectionWithBetaOption()
public void supportV6ConnectionWithBetaOption()
{
testConnection(V5, V5);
testConnection(NEWEST_BETA, V5);
testConnection(V6, V6);
testConnection(NEWEST_BETA, V6);
}
@Test
@ -176,6 +178,7 @@ public class ProtocolNegotiationTest extends CQLTester
{
if (expectError)
fail("Expected a protocol exception");
session.execute("SELECT * FROM system.local");
}
catch (Exception e)
{

View File

@ -80,8 +80,8 @@ public class ProtocolVersionTest
Assert.assertTrue(ProtocolVersion.supportedVersions().size() >= 2); // at least one OS and one DSE
Assert.assertNotNull(ProtocolVersion.CURRENT);
Assert.assertFalse(ProtocolVersion.V4.isBeta());
Assert.assertTrue(ProtocolVersion.V5.isBeta());
Assert.assertFalse(ProtocolVersion.V5.isBeta());
Assert.assertTrue(ProtocolVersion.V6.isBeta());
}
@Test
@ -92,28 +92,34 @@ public class ProtocolVersionTest
Assert.assertTrue(ProtocolVersion.V3.isSmallerOrEqualTo(ProtocolVersion.V3));
Assert.assertTrue(ProtocolVersion.V4.isSmallerOrEqualTo(ProtocolVersion.V4));
Assert.assertTrue(ProtocolVersion.V5.isSmallerOrEqualTo(ProtocolVersion.V5));
Assert.assertTrue(ProtocolVersion.V6.isSmallerOrEqualTo(ProtocolVersion.V6));
Assert.assertTrue(ProtocolVersion.V1.isGreaterOrEqualTo(ProtocolVersion.V1));
Assert.assertTrue(ProtocolVersion.V2.isGreaterOrEqualTo(ProtocolVersion.V2));
Assert.assertTrue(ProtocolVersion.V3.isGreaterOrEqualTo(ProtocolVersion.V3));
Assert.assertTrue(ProtocolVersion.V4.isGreaterOrEqualTo(ProtocolVersion.V4));
Assert.assertTrue(ProtocolVersion.V5.isGreaterOrEqualTo(ProtocolVersion.V5));
Assert.assertTrue(ProtocolVersion.V6.isGreaterOrEqualTo(ProtocolVersion.V6));
Assert.assertTrue(ProtocolVersion.V1.isSmallerThan(ProtocolVersion.V2));
Assert.assertTrue(ProtocolVersion.V2.isSmallerThan(ProtocolVersion.V3));
Assert.assertTrue(ProtocolVersion.V3.isSmallerThan(ProtocolVersion.V4));
Assert.assertTrue(ProtocolVersion.V4.isSmallerThan(ProtocolVersion.V5));
Assert.assertTrue(ProtocolVersion.V5.isSmallerThan(ProtocolVersion.V6));
Assert.assertFalse(ProtocolVersion.V1.isGreaterThan(ProtocolVersion.V2));
Assert.assertFalse(ProtocolVersion.V2.isGreaterThan(ProtocolVersion.V3));
Assert.assertFalse(ProtocolVersion.V3.isGreaterThan(ProtocolVersion.V4));
Assert.assertFalse(ProtocolVersion.V4.isGreaterThan(ProtocolVersion.V5));
Assert.assertFalse(ProtocolVersion.V5.isGreaterThan(ProtocolVersion.V6));
Assert.assertTrue(ProtocolVersion.V6.isGreaterThan(ProtocolVersion.V5));
Assert.assertTrue(ProtocolVersion.V5.isGreaterThan(ProtocolVersion.V4));
Assert.assertTrue(ProtocolVersion.V4.isGreaterThan(ProtocolVersion.V3));
Assert.assertTrue(ProtocolVersion.V3.isGreaterThan(ProtocolVersion.V2));
Assert.assertTrue(ProtocolVersion.V2.isGreaterThan(ProtocolVersion.V1));
Assert.assertFalse(ProtocolVersion.V6.isSmallerThan(ProtocolVersion.V5));
Assert.assertFalse(ProtocolVersion.V5.isSmallerThan(ProtocolVersion.V4));
Assert.assertFalse(ProtocolVersion.V4.isSmallerThan(ProtocolVersion.V3));
Assert.assertFalse(ProtocolVersion.V3.isSmallerThan(ProtocolVersion.V2));

View File

@ -133,7 +133,7 @@ public class SettingsMode implements Serializable
private static abstract class Cql3Options extends GroupedOptions
{
final OptionSimple api = new OptionSimple("cql3", "", null, "", true);
final OptionSimple protocolVersion = new OptionSimple("protocolVersion=", "[2-4]+", "NEWEST_SUPPORTED", "CQL Protocol Version", false);
final OptionSimple protocolVersion = new OptionSimple("protocolVersion=", "[2-5]+", "NEWEST_SUPPORTED", "CQL Protocol Version", false);
final OptionSimple useUnPrepared = new OptionSimple("unprepared", "", null, "force use of unprepared statements", false);
final OptionSimple useCompression = new OptionSimple("compression=", "none|lz4|snappy", "none", "", false);
final OptionSimple port = new OptionSimple("port=", "[0-9]+", "9046", "", false);