You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2014/12/09 21:10:00 UTC

cassandra git commit: Refuse Paxos operations with more than one pending endpoints

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.0 71e1219de -> 77df5578a


Refuse Paxos operations with more than one pending endpoints

patch by slebresne; reviewed by kohlisankalp for CASSANDRA-8346


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/77df5578
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/77df5578
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/77df5578

Branch: refs/heads/cassandra-2.0
Commit: 77df5578a0c80f9e8b5de914fa75d1bda023a4f5
Parents: 71e1219
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Tue Dec 9 21:08:48 2014 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Tue Dec 9 21:08:48 2014 +0100

----------------------------------------------------------------------
 CHANGES.txt                                           |  1 +
 .../cassandra/exceptions/UnavailableException.java    |  7 ++++++-
 .../org/apache/cassandra/service/StorageProxy.java    | 14 +++++++++++++-
 3 files changed, 20 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/77df5578/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 7c89e60..3c651ff 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.0.12:
+ * Refuse Paxos operation with more than one pending endpoint (CASSANDRA-8346)
  * Throw correct exception when trying to bind a keyspace or table
    name (CASSANDRA-6952)
  * Make HHOM.compact synchronized (CASSANDRA-8416)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/77df5578/src/java/org/apache/cassandra/exceptions/UnavailableException.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/exceptions/UnavailableException.java b/src/java/org/apache/cassandra/exceptions/UnavailableException.java
index e557550..baee0b2 100644
--- a/src/java/org/apache/cassandra/exceptions/UnavailableException.java
+++ b/src/java/org/apache/cassandra/exceptions/UnavailableException.java
@@ -27,7 +27,12 @@ public class UnavailableException extends RequestExecutionException
 
     public UnavailableException(ConsistencyLevel consistency, int required, int alive)
     {
-        super(ExceptionCode.UNAVAILABLE, "Cannot achieve consistency level " + consistency);
+        this("Cannot achieve consistency level " + consistency, consistency, required, alive);
+    }
+
+    public UnavailableException(String msg, ConsistencyLevel consistency, int required, int alive)
+    {
+        super(ExceptionCode.UNAVAILABLE, msg);
         this.consistency = consistency;
         this.required = required;
         this.alive = alive;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/77df5578/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index d8b6619..f877aee 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -304,6 +304,7 @@ public class StorageProxy implements StorageProxyMBean
         Token tk = StorageService.getPartitioner().getToken(key);
         List<InetAddress> naturalEndpoints = StorageService.instance.getNaturalEndpoints(keyspaceName, tk);
         Collection<InetAddress> pendingEndpoints = StorageService.instance.getTokenMetadata().pendingEndpointsFor(tk, keyspaceName);
+
         if (consistencyForPaxos == ConsistencyLevel.LOCAL_SERIAL)
         {
             // Restrict naturalEndpoints and pendingEndpoints to node in the local DC only
@@ -312,10 +313,21 @@ public class StorageProxy implements StorageProxyMBean
             naturalEndpoints = ImmutableList.copyOf(Iterables.filter(naturalEndpoints, isLocalDc));
             pendingEndpoints = ImmutableList.copyOf(Iterables.filter(pendingEndpoints, isLocalDc));
         }
-        int requiredParticipants = pendingEndpoints.size() + 1 + naturalEndpoints.size() / 2; // See CASSANDRA-833
+        int participants = pendingEndpoints.size() + naturalEndpoints.size();
+        int requiredParticipants = participants + 1  / 2; // See CASSANDRA-833
         List<InetAddress> liveEndpoints = ImmutableList.copyOf(Iterables.filter(Iterables.concat(naturalEndpoints, pendingEndpoints), IAsyncCallback.isAlive));
         if (liveEndpoints.size() < requiredParticipants)
             throw new UnavailableException(consistencyForPaxos, requiredParticipants, liveEndpoints.size());
+
+        // We cannot allow CAS operations with 2 or more pending endpoints, see #8346.
+        // Note that we fake an impossible number of required nodes in the unavailable exception
+        // to nail home the point that it's an impossible operation no matter how many nodes are live.
+        if (pendingEndpoints.size() > 1)
+            throw new UnavailableException(String.format("Cannot perform LWT operation as there is more than one (%d) pending range movement", pendingEndpoints.size()),
+                                           consistencyForPaxos,
+                                           participants + 1,
+                                           liveEndpoints.size());
+
         return Pair.create(liveEndpoints, requiredParticipants);
     }