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 2012/02/22 14:23:58 UTC

[4/4] git commit: Fix short read protection

Fix short read protection

patch by slebresne; reviewed by driftx for CASSANDRA-3934


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

Branch: refs/heads/trunk
Commit: 8413d831d12099e8f2764438f0f31ec8ea1830b0
Parents: 44ac7a0
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Wed Feb 22 14:21:53 2012 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Wed Feb 22 14:21:53 2012 +0100

----------------------------------------------------------------------
 CHANGES.txt                                        |    1 +
 .../cassandra/db/RetriedSliceFromReadCommand.java  |    2 +-
 .../apache/cassandra/db/SliceFromReadCommand.java  |   25 ++++++++++----
 3 files changed, 20 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/8413d831/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 5869d32..966f940 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -23,6 +23,7 @@
  * remove the wait on hint future during write (CASSANDRA-3870)
  * (cqlsh) ignore missing CfDef opts (CASSANDRA-3933)
  * (cqlsh) look for cqlshlib relative to realpath (CASSANDRA-3767)
+ * Fix short read protection (CASSANDRA-3934)
 Merged from 0.8:
  * (Pig) fix CassandraStorage to use correct comparator in Super ColumnFamily
    case (CASSANDRA-3251)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/8413d831/src/java/org/apache/cassandra/db/RetriedSliceFromReadCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RetriedSliceFromReadCommand.java b/src/java/org/apache/cassandra/db/RetriedSliceFromReadCommand.java
index 6890f9d..5e0ca13 100644
--- a/src/java/org/apache/cassandra/db/RetriedSliceFromReadCommand.java
+++ b/src/java/org/apache/cassandra/db/RetriedSliceFromReadCommand.java
@@ -53,7 +53,7 @@ public class RetriedSliceFromReadCommand extends SliceFromReadCommand
     }
 
     @Override
-    public int getRequestedCount()
+    public int getOriginalRequestedCount()
     {
         return originalCount;
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/8413d831/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SliceFromReadCommand.java b/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
index 51c1602..58b5e22 100644
--- a/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
+++ b/src/java/org/apache/cassandra/db/SliceFromReadCommand.java
@@ -76,10 +76,16 @@ public class SliceFromReadCommand extends ReadCommand
         int liveColumnsInRow = row != null ? row.cf.getLiveColumnCount() : 0;
 
         assert maxLiveColumns <= count;
-        if ((maxLiveColumns == count) && (liveColumnsInRow < count))
+        // We generate a retry if at least one node reply with count live columns but after merge we have less
+        // than the total number of column we are interested in (which may be < count on a retry)
+        if ((maxLiveColumns == count) && (liveColumnsInRow < getOriginalRequestedCount()))
         {
-            int retryCount = count + count - liveColumnsInRow;
-            return new RetriedSliceFromReadCommand(table, key, queryPath, start, finish, reversed, count, retryCount);
+            // We asked t (= count) live columns and got l (=liveColumnsInRow) ones.
+            // From that, we can estimate that on this row, for x requested
+            // columns, only l/t end up live after reconciliation. So for next
+            // round we want to ask x column so that x * (l/t) == t, i.e. x = t^2/l.
+            int retryCount = ((count * count) / liveColumnsInRow) + 1;
+            return new RetriedSliceFromReadCommand(table, key, queryPath, start, finish, reversed, getOriginalRequestedCount(), retryCount);
         }
 
         return null;
@@ -93,11 +99,11 @@ public class SliceFromReadCommand extends ReadCommand
 
         int liveColumnsInRow = row.cf.getLiveColumnCount();
 
-        if (liveColumnsInRow > getRequestedCount())
+        if (liveColumnsInRow > getOriginalRequestedCount())
         {
-            int columnsToTrim = liveColumnsInRow - getRequestedCount();
+            int columnsToTrim = liveColumnsInRow - getOriginalRequestedCount();
 
-            logger.debug("trimming {} live columns to the originally requested {}", row.cf.getLiveColumnCount(), getRequestedCount());
+            logger.debug("trimming {} live columns to the originally requested {}", row.cf.getLiveColumnCount(), getOriginalRequestedCount());
 
             Collection<IColumn> columns;
             if (reversed)
@@ -122,7 +128,12 @@ public class SliceFromReadCommand extends ReadCommand
         }
     }
 
-    protected int getRequestedCount()
+    /**
+     * The original number of columns requested by the user.
+     * This can be different from count when the slice command is a retry (see
+     * RetriedSliceFromReadCommand)
+     */
+    protected int getOriginalRequestedCount()
     {
         return count;
     }