Author: jbellis
Date: Mon Nov 22 19:27:13 2010
New Revision: 1037847

URL: http://svn.apache.org/viewvc?rev=1037847&view=rev
Log:
fix live-column-count of slice ranges including tombstoned supercolumn with 
live subcolumn
patch by jbellis and Tyler Hobbs; reviewed by tjake for CASSANDRA-1591

Modified:
    cassandra/branches/cassandra-0.6/CHANGES.txt
    
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/Column.java
    
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/IColumn.java
    
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/SuperColumn.java
    
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
    cassandra/branches/cassandra-0.6/test/system/test_server.py

Modified: cassandra/branches/cassandra-0.6/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/CHANGES.txt?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.6/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.6/CHANGES.txt Mon Nov 22 19:27:13 2010
@@ -8,6 +8,8 @@
  * Fix misuse of DataOutputBuffer.getData in AntiEntropyService
    (CASSANDRA-1729)
  * detect and warn when obsolete version of JNA is present (CASSANDRA-1770)
+ * fix live-column-count of slice ranges including tombstoned supercolumn 
+   with live subcolumn (CASSANDRA-1591)
 
 
 0.6.8

Modified: 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/Column.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/Column.java?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/Column.java 
(original)
+++ 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/Column.java 
Mon Nov 22 19:27:13 2010
@@ -221,5 +221,10 @@ public class Column implements IColumn
         sb.append(timestamp());
         return sb.toString();
     }
+
+    public boolean isLive()
+    {
+        return !isMarkedForDelete;
+    }
 }
 

Modified: 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/IColumn.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/IColumn.java?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/IColumn.java 
(original)
+++ 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/IColumn.java 
Mon Nov 22 19:27:13 2010
@@ -44,4 +44,11 @@ public interface IColumn
     public void updateDigest(MessageDigest digest);
     public int getLocalDeletionTime(); // for tombstone GC, so int is 
sufficient granularity
     public String getString(AbstractType comparator);
+
+    /**
+     * For a simple column, live == !isMarkedForDelete.
+     * For a supercolumn, live means it has at least one subcolumn whose 
timestamp is greater than the
+     * supercolumn deleted-at time.
+     */
+    boolean isLive();
 }

Modified: 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/SuperColumn.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/SuperColumn.java?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/SuperColumn.java
 (original)
+++ 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/SuperColumn.java
 Mon Nov 22 19:27:13 2010
@@ -268,6 +268,11 @@ public class SuperColumn implements ICol
         return sb.toString();
     }
 
+    public boolean isLive()
+    {
+        return mostRecentLiveChangeAt() > markedForDeleteAt.get();
+    }
+
     public int getLocalDeletionTime()
     {
         return localDeletionTime.get();

Modified: 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
 (original)
+++ 
cassandra/branches/cassandra-0.6/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
 Mon Nov 22 19:27:13 2010
@@ -121,7 +121,7 @@ public class SliceQueryFilter extends Qu
                 break;
 
             // only count live columns towards the `count` criteria
-            if (!column.isMarkedForDelete()
+            if (column.isLive() 
                 && (!container.isMarkedForDelete()
                     || column.mostRecentLiveChangeAt() > 
container.getMarkedForDeleteAt()))
             {

Modified: cassandra/branches/cassandra-0.6/test/system/test_server.py
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.6/test/system/test_server.py?rev=1037847&r1=1037846&r2=1037847&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.6/test/system/test_server.py (original)
+++ cassandra/branches/cassandra-0.6/test/system/test_server.py Mon Nov 22 
19:27:13 2010
@@ -850,7 +850,30 @@ class TestMutations(CassandraTester):
         result = client.get_range_slice("Keyspace2", cp, 
SlicePredicate(column_names=['sc1']), 'key2', 'key4', 5, ConsistencyLevel.ONE)
         assert len(result) == 3
         assert list(set(row.columns[0].super_column.name for row in 
result))[0] == 'sc1'
-        
+
+    def test_get_range_slice_after_deletion(self):
+        key = 'key1'
+        # three supercoluns, each with "col1" subcolumn
+        for i in range(1,4):
+            client.insert('Keyspace2', key, ColumnPath('Super3', 'sc%d' % i, 
'col1'), 'val1', 0, ConsistencyLevel.ONE)
+
+        cp = ColumnParent('Super3')
+        predicate = SlicePredicate(slice_range=SliceRange('sc1', 'sc3', False, 
count=1))
+        k_range = KeyRange(start_key=key, end_key=key, count=1)
+
+        # validate count=1 restricts to 1 supercolumn
+        result = client.get_range_slices('Keyspace2', cp, predicate, k_range, 
ConsistencyLevel.ONE)
+        assert len(result[0].columns) == 1
+
+        # remove sc1; add back subcolumn to override tombstone
+        client.remove('Keyspace2', key, ColumnPath('Super3', 'sc1'), 1, 
ConsistencyLevel.ONE)
+        result = client.get_range_slices('Keyspace2', cp, predicate, k_range, 
ConsistencyLevel.ONE)
+        assert len(result[0].columns) == 1
+        client.insert('Keyspace2', key, ColumnPath('Super3', 'sc1', 'col1'), 
'val1', 2, ConsistencyLevel.ONE)
+        result = client.get_range_slices('Keyspace2', cp, predicate, k_range, 
ConsistencyLevel.ONE)
+        assert len(result[0].columns) == 1, result[0].columns
+        assert result[0].columns[0].super_column.name == 'sc1'
+
     def test_get_range_slice(self):
         for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
             for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:


Reply via email to