Don't clear out range tombstones during compaction.

Patch by rlow; reviewed by marcuse for CASSANDRA-7808
This commit is contained in:
Marcus Eriksson 2014-08-26 11:33:24 +02:00
parent 62642fa97e
commit 1cf986301b
3 changed files with 66 additions and 3 deletions

View File

@ -11,6 +11,7 @@
are thrown while handling native protocol messages (CASSANDRA-7470)
* Fix row size miscalculation in LazilyCompactedRow (CASSANDRA-7543)
* Fix race in background compaction check (CASSANDRA-7745)
* Don't clear out range tombstones during compaction (CASSANDRA-7808)
1.2.18

View File

@ -167,8 +167,9 @@ public class LazilyCompactedRow extends AbstractCompactedRow implements Iterable
public boolean isEmpty()
{
// need to clone emptyColumnFamily to avoid resetting the deletion time. See CASSANDRA-7808.
boolean cfIrrelevant = shouldPurge
? ColumnFamilyStore.removeDeletedCF(emptyColumnFamily, controller.gcBefore) == null
? ColumnFamilyStore.removeDeletedCF(emptyColumnFamily.cloneMeShallow(), controller.gcBefore) == null
: !emptyColumnFamily.isMarkedForDelete(); // tombstones are relevant
return cfIrrelevant && columnStats.columnCount == 0;
}
@ -285,11 +286,12 @@ public class LazilyCompactedRow extends AbstractCompactedRow implements Iterable
ColumnFamily purged = PrecompactedRow.removeDeletedAndOldShards(key, shouldPurge, controller, container);
if (purged == null || !purged.iterator().hasNext())
{
container.clear();
// don't call clear() because that resets the deletion time. See CASSANDRA-7808.
container = emptyColumnFamily.cloneMeShallow();
return null;
}
IColumn reduced = purged.iterator().next();
container.clear();
container = emptyColumnFamily.cloneMeShallow();
// PrecompactedRow.removeDeletedAndOldShards have only checked the top-level CF deletion times,
// not the range tombstone. For that we use the columnIndexer tombstone tracker.

View File

@ -18,17 +18,22 @@
*/
package org.apache.cassandra.db;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.Util;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.utils.ByteBufferUtil;
import static org.apache.cassandra.Util.dk;
import static org.junit.Assert.assertEquals;
public class RangeTombstoneTest extends SchemaLoader
{
@ -96,6 +101,61 @@ public class RangeTombstoneTest extends SchemaLoader
assert !isLive(cf, cf.getColumn(b(i))) : "Column " + i + " shouldn't be live";
}
@Test
public void test7808_1() throws ExecutionException, InterruptedException
{
DatabaseDescriptor.setInMemoryCompactionLimit(0);
Table table = Table.open(KSNAME);
ColumnFamilyStore cfs = table.getColumnFamilyStore(CFNAME);
cfs.metadata.gcGraceSeconds(2);
String key = "7808_1";
RowMutation rm;
rm = new RowMutation(KSNAME, ByteBufferUtil.bytes(key));
for (int i = 0; i < 40; i += 2)
add(rm, i, 0);
rm.apply();
cfs.forceBlockingFlush();
rm = new RowMutation(KSNAME, ByteBufferUtil.bytes(key));
ColumnFamily cf = rm.addOrGet(CFNAME);
cf.delete(new DeletionInfo(1, 1));
rm.apply();
cfs.forceBlockingFlush();
Thread.sleep(5);
cfs.forceMajorCompaction();
}
@Test
public void test7808_2() throws ExecutionException, InterruptedException, IOException
{
DatabaseDescriptor.setInMemoryCompactionLimit(0);
Table table = Table.open(KSNAME);
ColumnFamilyStore cfs = table.getColumnFamilyStore(CFNAME);
cfs.metadata.gcGraceSeconds(2);
String key = "7808_2";
RowMutation rm;
rm = new RowMutation(KSNAME, ByteBufferUtil.bytes(key));
for (int i = 10; i < 20; i++)
add(rm, i, 0);
rm.apply();
cfs.forceBlockingFlush();
rm = new RowMutation(KSNAME, ByteBufferUtil.bytes(key));
ColumnFamily cf = rm.addOrGet(CFNAME);
cf.delete(new DeletionInfo(0,0));
rm.apply();
rm = new RowMutation(KSNAME, ByteBufferUtil.bytes(key));
add(rm, 5, 1);
rm.apply();
cfs.forceBlockingFlush();
Thread.sleep(5);
cfs.forceMajorCompaction();
assertEquals(1, Util.getColumnFamily(table, Util.dk(key), CFNAME).getColumnCount());
}
@Test
public void overlappingRangeTest() throws Exception
{