diff --git a/CHANGES.txt b/CHANGES.txt index b1dcbe1a5e..7fa995de63 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.16 + * Don't write shadowed range tombstone (CASSANDRA-12030) * Fix filtering on clustering columns when 2i is used (CASSANDRA-11907) * Reduce contention getting instances of CompositeType (CASSANDRA-10433) * Improve digest calculation in the presence of overlapping tombstones (CASSANDRA-11349) diff --git a/src/java/org/apache/cassandra/db/compaction/LazilyCompactedRow.java b/src/java/org/apache/cassandra/db/compaction/LazilyCompactedRow.java index f912da236e..dab5eebdd4 100644 --- a/src/java/org/apache/cassandra/db/compaction/LazilyCompactedRow.java +++ b/src/java/org/apache/cassandra/db/compaction/LazilyCompactedRow.java @@ -286,7 +286,8 @@ public class LazilyCompactedRow extends AbstractCompactedRow RangeTombstone t = tombstone; tombstone = null; - if (t.data.isGcAble(controller.gcBefore) && t.timestamp() < getMaxPurgeableTimestamp()) + if (t.data.isGcAble(controller.gcBefore) && t.timestamp() < getMaxPurgeableTimestamp() || + maxRowTombstone.markedForDeleteAt >= t.timestamp()) { indexBuilder.tombstoneTracker().update(t, true); return null; diff --git a/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java b/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java index 32924221fa..dfd6960af6 100644 --- a/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java +++ b/test/unit/org/apache/cassandra/db/RangeTombstoneTest.java @@ -39,6 +39,7 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.IndexType; import org.apache.cassandra.db.columniterator.OnDiskAtomIterator; import org.apache.cassandra.db.compaction.CompactionManager; +import org.apache.cassandra.db.compaction.LeveledCompactionStrategy; import org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy; import org.apache.cassandra.db.composites.CellName; import org.apache.cassandra.db.composites.CellNames; @@ -542,6 +543,45 @@ public class RangeTombstoneTest extends SchemaLoader assertEquals(2, cnt); } + @Test + public void testCompactionOfRangeTombstonesCoveredByRowTombstone() throws Exception + { + long testTimeStamp = 1451606400L; // 01/01/2016 : 00:00:00 GMT + Keyspace table = Keyspace.open(KSNAME); + ColumnFamilyStore cfs = table.getColumnFamilyStore(CFNAME); + ByteBuffer key = ByteBufferUtil.bytes("k4"); + + // remove any existing sstables before starting + cfs.truncateBlocking(); + cfs.disableAutoCompaction(); + cfs.setCompactionStrategyClass(LeveledCompactionStrategy.class.getCanonicalName()); + + Mutation rm = new Mutation(KSNAME, key); + for (int i = 1; i < 11; i += 2, testTimeStamp += i * 10) + add(rm, i, testTimeStamp); + rm.apply(); + cfs.forceBlockingFlush(); + + rm = new Mutation(KSNAME, key); + ColumnFamily cf = rm.addOrGet(CFNAME); + + // Write the covering row tombstone + cf.delete(new DeletionTime(++testTimeStamp, (int) testTimeStamp)); + + // Create range tombstones covered by row tombstone above. + for (int i = 1; i < 11; i += 2, testTimeStamp -= i * 5) + delete(cf, 0, 7, testTimeStamp); + rm.apply(); + cfs.forceBlockingFlush(); + + // there should be 2 sstables + assertEquals(2, cfs.getSSTables().size()); + + // compact down to nothing + CompactionManager.instance.performMaximal(cfs); + assertEquals(0, cfs.getSSTables().size()); + } + @Test public void testOverwritesToDeletedColumns() throws Exception {