mirror of https://github.com/apache/cassandra
fix mixing user-provided timestamps and local deletion time for #4396
This commit is contained in:
parent
5bcfcbc3ed
commit
84a1d6059b
|
|
@ -256,8 +256,9 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
|
|||
if (isMarkedForDelete() && getLocalDeletionTime() < gcBefore)
|
||||
return true;
|
||||
|
||||
long deletedAt = getMarkedForDeleteAt();
|
||||
for (IColumn column : columns)
|
||||
if (column.mostRecentLiveChangeAt() < getLocalDeletionTime() || column.hasIrrelevantData(gcBefore))
|
||||
if (column.mostRecentLiveChangeAt() <= deletedAt || column.hasIrrelevantData(gcBefore))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -35,11 +35,14 @@ import org.apache.cassandra.CleanupHelper;
|
|||
import org.apache.cassandra.Util;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
import org.apache.cassandra.db.*;
|
||||
import org.apache.cassandra.db.columniterator.IColumnIterator;
|
||||
import org.apache.cassandra.db.columniterator.IdentityQueryFilter;
|
||||
import org.apache.cassandra.db.compaction.OperationType;
|
||||
import org.apache.cassandra.db.filter.QueryFilter;
|
||||
import org.apache.cassandra.db.filter.QueryPath;
|
||||
import org.apache.cassandra.io.sstable.*;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
|
||||
public class CompactionsTest extends CleanupHelper
|
||||
{
|
||||
|
|
@ -128,6 +131,43 @@ public class CompactionsTest extends CleanupHelper
|
|||
assertMaxTimestamp(store, maxTimestampExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuperColumnTombstones() throws IOException, ExecutionException, InterruptedException
|
||||
{
|
||||
Table table = Table.open(TABLE1);
|
||||
ColumnFamilyStore cfs = table.getColumnFamilyStore("Super1");
|
||||
cfs.disableAutoCompaction();
|
||||
|
||||
DecoratedKey key = Util.dk("tskey");
|
||||
ByteBuffer scName = ByteBufferUtil.bytes("TestSuperColumn");
|
||||
|
||||
// a subcolumn
|
||||
RowMutation rm = new RowMutation(TABLE1, key.key);
|
||||
rm.add(new QueryPath("Super1", scName, ByteBufferUtil.bytes(0)),
|
||||
ByteBufferUtil.EMPTY_BYTE_BUFFER,
|
||||
FBUtilities.timestampMicros());
|
||||
rm.apply();
|
||||
cfs.forceBlockingFlush();
|
||||
|
||||
// shadow the subcolumn with a supercolumn tombstone
|
||||
rm = new RowMutation(TABLE1, key.key);
|
||||
rm.delete(new QueryPath("Super1", scName), FBUtilities.timestampMicros());
|
||||
rm.apply();
|
||||
cfs.forceBlockingFlush();
|
||||
|
||||
CompactionManager.instance.performMaximal(cfs);
|
||||
assertEquals(1, cfs.getSSTables().size());
|
||||
|
||||
// check that the shadowed column is gone
|
||||
SSTableReader sstable = cfs.getSSTables().iterator().next();
|
||||
SSTableScanner scanner = sstable.getScanner(new QueryFilter(null, new QueryPath("Super1", scName), new IdentityQueryFilter()));
|
||||
scanner.seekTo(key);
|
||||
IColumnIterator iter = scanner.next();
|
||||
assertEquals(key, iter.getKey());
|
||||
SuperColumn sc = (SuperColumn) iter.next();
|
||||
assert sc.getSubColumns().isEmpty();
|
||||
}
|
||||
|
||||
public void assertMaxTimestamp(ColumnFamilyStore store, long maxTimestampExpected)
|
||||
{
|
||||
long maxTimestampObserved = Long.MIN_VALUE;
|
||||
|
|
|
|||
Loading…
Reference in New Issue