Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 068EC10D96 for ; Tue, 9 Dec 2014 20:10:01 +0000 (UTC) Received: (qmail 68704 invoked by uid 500); 9 Dec 2014 20:10:00 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 68666 invoked by uid 500); 9 Dec 2014 20:10:00 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 68653 invoked by uid 99); 9 Dec 2014 20:10:00 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 09 Dec 2014 20:10:00 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8400AA21A45; Tue, 9 Dec 2014 20:10:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: slebresne@apache.org To: commits@cassandra.apache.org Message-Id: <8b185d1d35d84270bd35b0f40bdcfe68@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cassandra git commit: Refuse Paxos operations with more than one pending endpoints Date: Tue, 9 Dec 2014 20:10:00 +0000 (UTC) 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 Authored: Tue Dec 9 21:08:48 2014 +0100 Committer: Sylvain Lebresne 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 naturalEndpoints = StorageService.instance.getNaturalEndpoints(keyspaceName, tk); Collection 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 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); }