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']: