Nodetool garbagecollect should retain SSTableLevel for LCS

Patch by Scott Carey; reviewed by marcuse for CASSANDRA-16634
This commit is contained in:
Scott Carey 2021-04-26 15:29:38 -07:00 committed by Marcus Eriksson
parent 354b87a0f6
commit a68a7c5181
4 changed files with 72 additions and 0 deletions

View File

@ -1,4 +1,5 @@
3.11.11
* Nodetool garbagecollect should retain SSTableLevel for LCS (CASSANDRA-16634)
* Ignore stale acks received in the shadow round (CASSANDRA-16588)
* Add autocomplete and error messages for provide_overlapping_tombstones (CASSANDRA-16350)
* Add StorageServiceMBean.getKeyspaceReplicationInfo(keyspaceName) (CASSANDRA-16447)

View File

@ -531,6 +531,12 @@ public class CompactionManager implements CompactionManagerMBean
{
return new CompactionController(cfStore, toCompact, gcBefore, null, tombstoneOption);
}
@Override
protected int getLevel()
{
return txn.onlyOne().getSSTableLevel();
}
};
task.setUserDefined(true);
task.setCompactionType(OperationType.GARBAGE_COLLECT);

View File

@ -229,6 +229,7 @@ public class GcCompactionBench extends CQLTester
int startTombCount = countTombstoneMarkers(cfs);
int startRowDeletions = countRowDeletions(cfs);
int startTableCount = cfs.getLiveSSTables().size();
int startTableMaxLevel = cfs.getLiveSSTables().stream().mapToInt(SSTableReader::getSSTableLevel).max().orElseGet(() -> 0);
long startSize = SSTableReader.getTotalBytes(cfs.getLiveSSTables());
System.out.println();
@ -242,6 +243,7 @@ public class GcCompactionBench extends CQLTester
int endTombCount = countTombstoneMarkers(cfs);
int endRowDeletions = countRowDeletions(cfs);
int endTableCount = cfs.getLiveSSTables().size();
int endTableMaxLevel = cfs.getLiveSSTables().stream().mapToInt(SSTableReader::getSSTableLevel).max().orElseGet(() -> 0);
long endSize = SSTableReader.getTotalBytes(cfs.getLiveSSTables());
System.out.println(cfs.getCompactionParametersJson());
@ -253,9 +255,11 @@ public class GcCompactionBench extends CQLTester
startTableCount, startSize, startRowCount, startRowDeletions, startTombCount));
System.out.println(String.format("At end: %12d tables %12d bytes %12d rows %12d deleted rows %12d tombstone markers",
endTableCount, endSize, endRowCount, endRowDeletions, endTombCount));
System.out.println(String.format("Max SSTable level before: %d and after %d", startTableMaxLevel, endTableMaxLevel));
String hashesAfter = getHashes();
Assert.assertEquals(hashesBefore, hashesAfter);
Assert.assertEquals(startTableMaxLevel, endTableMaxLevel);
}
private String getHashes() throws Throwable

View File

@ -36,6 +36,7 @@ import org.apache.cassandra.db.rows.*;
import org.apache.cassandra.io.sstable.ISSTableScanner;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.schema.CompactionParams;
import org.apache.cassandra.schema.CompactionParams.TombstoneOption;
import org.apache.cassandra.utils.FBUtilities;
public class GcCompactionTest extends CQLTester
@ -150,6 +151,66 @@ public class GcCompactionTest extends CQLTester
assertTrue(rowCount > countRows(table3));
}
@Test
public void testGarbageCollectRetainsLCSLevel() throws Throwable
{
createTable("CREATE TABLE %s(" +
" key int," +
" column int," +
" data int," +
" PRIMARY KEY ((key), column)" +
") WITH compaction = { 'class' : 'LeveledCompactionStrategy' };");
assertEquals("LeveledCompactionStrategy", getCurrentColumnFamilyStore().getCompactionStrategyManager().getName());
for (int i = 0; i < KEY_COUNT; ++i)
for (int j = 0; j < CLUSTERING_COUNT; ++j)
execute("INSERT INTO %s (key, column, data) VALUES (?, ?, ?)", i, j, i * j + j);
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
cfs.disableAutoCompaction();
flush();
assertEquals(1, cfs.getLiveSSTables().size());
SSTableReader table = cfs.getLiveSSTables().iterator().next();
int gen = table.descriptor.generation;
assertEquals(KEY_COUNT * CLUSTERING_COUNT, countRows(table));
assertEquals(0, table.getSSTableLevel()); // flush writes to L0
CompactionManager.AllSSTableOpStatus status;
status = CompactionManager.instance.performGarbageCollection(cfs, TombstoneOption.ROW, 1);
assertEquals(CompactionManager.AllSSTableOpStatus.SUCCESSFUL, status);
assertEquals(1, cfs.getLiveSSTables().size());
SSTableReader collected = cfs.getLiveSSTables().iterator().next();
int collectedGen = collected.descriptor.generation;
assertTrue(collectedGen > gen);
assertEquals(KEY_COUNT * CLUSTERING_COUNT, countRows(collected));
assertEquals(0, collected.getSSTableLevel()); // garbagecollect should leave the LCS level where it was
CompactionManager.instance.performMaximal(cfs, false);
assertEquals(1, cfs.getLiveSSTables().size());
SSTableReader compacted = cfs.getLiveSSTables().iterator().next();
int compactedGen = compacted.descriptor.generation;
assertTrue(compactedGen > collectedGen);
assertEquals(KEY_COUNT * CLUSTERING_COUNT, countRows(compacted));
assertEquals(1, compacted.getSSTableLevel()); // full compaction with LCS should move to L1
status = CompactionManager.instance.performGarbageCollection(cfs, TombstoneOption.ROW, 1);
assertEquals(CompactionManager.AllSSTableOpStatus.SUCCESSFUL, status);
assertEquals(1, cfs.getLiveSSTables().size());
SSTableReader collected2 = cfs.getLiveSSTables().iterator().next();
assertTrue(collected2.descriptor.generation > compactedGen);
assertEquals(KEY_COUNT * CLUSTERING_COUNT, countRows(collected2));
assertEquals(1, collected2.getSSTableLevel()); // garbagecollect should leave the LCS level where it was
}
@Test
public void testGarbageCollectOrder() throws Throwable
{