diff --git a/bin/cqlsh b/bin/cqlsh index 7883f9f2ce..a062dcdc1a 100755 --- a/bin/cqlsh +++ b/bin/cqlsh @@ -240,6 +240,7 @@ cqlsh_extra_syntax_rules = r''' | "THREE" | "QUORUM" | "ALL" + | "LOCAL_ONE" | "LOCAL_QUORUM" | "EACH_QUORUM" ; @@ -1757,7 +1758,7 @@ class Shell(cmd.Cmd): Valid consistency levels: - ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_QUORUM and EACH_QUORUM. + ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_ONE, LOCAL_QUORUM and EACH_QUORUM. CONSISTENCY diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile index 63ec71ac26..c90b585aae 100644 --- a/doc/cql3/CQL.textile +++ b/doc/cql3/CQL.textile @@ -1039,6 +1039,7 @@ CQL distinguishes between _reserved_ and _non-reserved_ keywords. Reserved keywo | @KEYSPACE@ | yes | | @LEVEL@ | no | | @LIMIT@ | yes | +| @LOCAL_ONE@ | yes | | @LOCAL_QUORUM@ | yes | | @MODIFY@ | yes | | @NORECURSIVE@ | yes | diff --git a/doc/native_protocol_v1.spec b/doc/native_protocol_v1.spec index b7a1de53d2..0d2ff05ca0 100644 --- a/doc/native_protocol_v1.spec +++ b/doc/native_protocol_v1.spec @@ -201,6 +201,7 @@ Table of Contents 0x0005 ALL 0x0006 LOCAL_QUORUM 0x0007 EACH_QUORUM + 0x0010 LOCAL_ONE [string map] A [short] n, followed by n pair where and are [string]. diff --git a/doc/native_protocol_v2.spec b/doc/native_protocol_v2.spec index b0449bbfb2..28c769ab78 100644 --- a/doc/native_protocol_v2.spec +++ b/doc/native_protocol_v2.spec @@ -220,6 +220,7 @@ Table of Contents 0x0007 EACH_QUORUM 0x0008 SERIAL 0x0009 LOCAL_SERIAL + 0x0010 LOCAL_ONE [string map] A [short] n, followed by n pair where and are [string]. diff --git a/interface/cassandra.thrift b/interface/cassandra.thrift index c42554d599..0948140e24 100644 --- a/interface/cassandra.thrift +++ b/interface/cassandra.thrift @@ -55,7 +55,7 @@ namespace rb CassandraThrift # An effort should be made not to break forward-client-compatibility either # (e.g. one should avoid removing obsolete fields from the IDL), but no # guarantees in this respect are made by the Cassandra project. -const string VERSION = "19.37.0" +const string VERSION = "19.38.0" # @@ -212,6 +212,7 @@ exception SchemaDisagreementException { * TWO Ensure that the write has been written to at least 2 node's commit log and memory table * THREE Ensure that the write has been written to at least 3 node's commit log and memory table * QUORUM Ensure that the write has been written to / 2 + 1 nodes + * LOCAL_ONE Ensure that the write has been written to 1 node within the local datacenter (requires NetworkTopologyStrategy) * LOCAL_QUORUM Ensure that the write has been written to / 2 + 1 nodes, within the local datacenter (requires NetworkTopologyStrategy) * EACH_QUORUM Ensure that the write has been written to / 2 + 1 nodes in each datacenter (requires NetworkTopologyStrategy) * ALL Ensure that the write is written to <ReplicationFactor> nodes before responding to the client. @@ -222,6 +223,7 @@ exception SchemaDisagreementException { * TWO Returns the record with the most recent timestamp once two replicas have replied. * THREE Returns the record with the most recent timestamp once three replicas have replied. * QUORUM Returns the record with the most recent timestamp once a majority of replicas have replied. + * LOCAL_ONE Returns the record with the most recent timestamp once a single replica within the local datacenter have replied. * LOCAL_QUORUM Returns the record with the most recent timestamp once a majority of replicas within the local datacenter have replied. * EACH_QUORUM Returns the record with the most recent timestamp once a majority of replicas within each datacenter have replied. * ALL Returns the record with the most recent timestamp once all replicas have replied (implies no replica may be down).. @@ -237,6 +239,7 @@ enum ConsistencyLevel { THREE = 8, SERIAL = 9, LOCAL_SERIAL = 10, + LOCAL_ONE = 11, } /** diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/ConsistencyLevel.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/ConsistencyLevel.java index ea92479ea5..ec5080a05d 100644 --- a/interface/thrift/gen-java/org/apache/cassandra/thrift/ConsistencyLevel.java +++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/ConsistencyLevel.java @@ -60,6 +60,7 @@ import org.apache.thrift.TEnum; * TWO Ensure that the write has been written to at least 2 node's commit log and memory table * THREE Ensure that the write has been written to at least 3 node's commit log and memory table * QUORUM Ensure that the write has been written to / 2 + 1 nodes + * LOCAL_ONE Ensure that the write has been written to 1 node within the local datacenter (requires NetworkTopologyStrategy) * LOCAL_QUORUM Ensure that the write has been written to / 2 + 1 nodes, within the local datacenter (requires NetworkTopologyStrategy) * EACH_QUORUM Ensure that the write has been written to / 2 + 1 nodes in each datacenter (requires NetworkTopologyStrategy) * ALL Ensure that the write is written to <ReplicationFactor> nodes before responding to the client. @@ -70,6 +71,7 @@ import org.apache.thrift.TEnum; * TWO Returns the record with the most recent timestamp once two replicas have replied. * THREE Returns the record with the most recent timestamp once three replicas have replied. * QUORUM Returns the record with the most recent timestamp once a majority of replicas have replied. + * LOCAL_ONE Returns the record with the most recent timestamp once a single replica within the local datacenter have replied. * LOCAL_QUORUM Returns the record with the most recent timestamp once a majority of replicas within the local datacenter have replied. * EACH_QUORUM Returns the record with the most recent timestamp once a majority of replicas within each datacenter have replied. * ALL Returns the record with the most recent timestamp once all replicas have replied (implies no replica may be down).. @@ -84,7 +86,8 @@ public enum ConsistencyLevel implements org.apache.thrift.TEnum { TWO(7), THREE(8), SERIAL(9), - LOCAL_SERIAL(10); + LOCAL_SERIAL(10), + LOCAL_ONE(11); private final int value; @@ -125,6 +128,8 @@ public enum ConsistencyLevel implements org.apache.thrift.TEnum { return SERIAL; case 10: return LOCAL_SERIAL; + case 11: + return LOCAL_ONE; default: return null; } diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java index c28519a6d9..a2c482e041 100644 --- a/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java +++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/cassandraConstants.java @@ -56,6 +56,6 @@ import org.slf4j.LoggerFactory; public class cassandraConstants { - public static final String VERSION = "19.37.0"; + public static final String VERSION = "19.38.0"; } diff --git a/lib/cql-internal-only-1.4.0.zip b/lib/cql-internal-only-1.4.0.zip index d800b923b7..fa33a3a1f9 100644 Binary files a/lib/cql-internal-only-1.4.0.zip and b/lib/cql-internal-only-1.4.0.zip differ diff --git a/src/java/org/apache/cassandra/db/ConsistencyLevel.java b/src/java/org/apache/cassandra/db/ConsistencyLevel.java index 956ab58289..5f17907274 100644 --- a/src/java/org/apache/cassandra/db/ConsistencyLevel.java +++ b/src/java/org/apache/cassandra/db/ConsistencyLevel.java @@ -46,15 +46,17 @@ public enum ConsistencyLevel THREE (3), QUORUM (4), ALL (5), - LOCAL_QUORUM(6), + LOCAL_QUORUM(6, true), EACH_QUORUM (7), SERIAL (8), - LOCAL_SERIAL(9); + LOCAL_SERIAL(9), + LOCAL_ONE (10, true); private static final Logger logger = LoggerFactory.getLogger(ConsistencyLevel.class); // Used by the binary protocol public final int code; + private final boolean isDCLocal; private static final ConsistencyLevel[] codeIdx; static { @@ -71,8 +73,14 @@ public enum ConsistencyLevel } private ConsistencyLevel(int code) + { + this(code, false); + } + + private ConsistencyLevel(int code, boolean isDCLocal) { this.code = code; + this.isDCLocal = isDCLocal; } public static ConsistencyLevel fromCode(int code) @@ -92,6 +100,7 @@ public enum ConsistencyLevel switch (this) { case ONE: + case LOCAL_ONE: return 1; case ANY: return 1; @@ -116,6 +125,11 @@ public enum ConsistencyLevel } } + public boolean isDatacenterLocal() + { + return isDCLocal; + } + private boolean isLocal(InetAddress endpoint) { return DatabaseDescriptor.getLocalDataCenter().equals(DatabaseDescriptor.getEndpointSnitch().getDatacenter(endpoint)); @@ -155,11 +169,11 @@ public enum ConsistencyLevel { /* * Endpoints are expected to be restricted to live replicas, sorted by snitch preference. - * For LOCAL_QORUM, move local-DC replicas in front first as we need them there whether + * For LOCAL_QUORUM, move local-DC replicas in front first as we need them there whether * we do read repair (since the first replica gets the data read) or not (since we'll take * the blockFor first ones). */ - if (this == LOCAL_QUORUM) + if (isDCLocal) Collections.sort(liveEndpoints, DatabaseDescriptor.getLocalComparator()); switch (readRepair) @@ -195,6 +209,8 @@ public enum ConsistencyLevel case ANY: // local hint is acceptable, and local node is always live return true; + case LOCAL_ONE: + return countLocalEndpoints(liveEndpoints) >= 1; case LOCAL_QUORUM: return countLocalEndpoints(liveEndpoints) >= blockFor(keyspace); case EACH_QUORUM: @@ -260,6 +276,7 @@ public enum ConsistencyLevel switch (this) { case LOCAL_QUORUM: + case LOCAL_ONE: requireNetworkTopologyStrategy(keyspaceName); break; case ANY: @@ -275,6 +292,7 @@ public enum ConsistencyLevel { case LOCAL_QUORUM: case EACH_QUORUM: + case LOCAL_ONE: requireNetworkTopologyStrategy(keyspaceName); break; case SERIAL: @@ -290,6 +308,7 @@ public enum ConsistencyLevel { case LOCAL_QUORUM: case EACH_QUORUM: + case LOCAL_ONE: requireNetworkTopologyStrategy(keyspaceName); break; case SERIAL: @@ -315,7 +334,7 @@ public enum ConsistencyLevel { throw new InvalidRequestException("Consistency level ANY is not yet supported for counter columnfamily " + metadata.cfName); } - else if (!metadata.getReplicateOnWrite() && this != ConsistencyLevel.ONE) + else if (!metadata.getReplicateOnWrite() && !(this == ConsistencyLevel.ONE || this == ConsistencyLevel.LOCAL_ONE)) { throw new InvalidRequestException("cannot achieve CL > CL.ONE without replicate_on_write on columnfamily " + metadata.cfName); } diff --git a/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java b/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java index 2a01fed345..f83c889929 100644 --- a/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java +++ b/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java @@ -122,7 +122,7 @@ public abstract class AbstractReplicationStrategy public AbstractWriteResponseHandler getWriteResponseHandler(Collection naturalEndpoints, Collection pendingEndpoints, ConsistencyLevel consistency_level, Runnable callback, WriteType writeType) { - if (consistency_level == ConsistencyLevel.LOCAL_QUORUM) + if (consistency_level.isDatacenterLocal()) { // block for in this context will be localnodes block. return new DatacenterWriteResponseHandler(naturalEndpoints, pendingEndpoints, consistency_level, getKeyspace(), callback, writeType); diff --git a/src/java/org/apache/cassandra/service/DatacenterWriteResponseHandler.java b/src/java/org/apache/cassandra/service/DatacenterWriteResponseHandler.java index 245565568e..5530374c3c 100644 --- a/src/java/org/apache/cassandra/service/DatacenterWriteResponseHandler.java +++ b/src/java/org/apache/cassandra/service/DatacenterWriteResponseHandler.java @@ -42,7 +42,7 @@ public class DatacenterWriteResponseHandler extends WriteResponseHandler WriteType writeType) { super(naturalEndpoints, pendingEndpoints, consistencyLevel, keyspace, callback, writeType); - assert consistencyLevel == ConsistencyLevel.LOCAL_QUORUM; + assert consistencyLevel.isDatacenterLocal(); } @Override diff --git a/src/java/org/apache/cassandra/service/ReadCallback.java b/src/java/org/apache/cassandra/service/ReadCallback.java index 7f9c19271b..b7d53800c5 100644 --- a/src/java/org/apache/cassandra/service/ReadCallback.java +++ b/src/java/org/apache/cassandra/service/ReadCallback.java @@ -127,7 +127,7 @@ public class ReadCallback implements IAsyncCallback