Make PartitionRowAccountingTest tests robust to memtable flushes

(cherry picked from commit 4efc40af90317e2794424fea09c2661fc9b51a2b)
This commit is contained in:
Dmitry Konstantinov 2026-07-28 20:39:47 +01:00
parent ce353ffe9f
commit 5119cb1c02
1 changed files with 37 additions and 0 deletions

View File

@ -33,10 +33,12 @@ import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.Memtable;
import org.apache.cassandra.utils.btree.BTree;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertSame;
/**
* Row-level analogue of {@link SetCellAccountingTest}. Where that test grows/resets a single {@code set<text>}
@ -63,6 +65,7 @@ public class PartitionRowAccountingTest extends CQLTester
confField.setAccessible(true);
Config conf = (Config) confField.get(null);
conf.memtable_allocation_type = Config.MemtableAllocationType.offheap_objects;
conf.memtable_cleanup_threshold = 0.8f; // to reduce risk of memtable switch during a test
}
catch (ReflectiveOperationException e)
{
@ -71,6 +74,13 @@ public class PartitionRowAccountingTest extends CQLTester
CQLTester.prepareServer();
}
private static void flushAllToBaseline()
{
for (Keyspace ks : Keyspace.all())
for (ColumnFamilyStore c : ks.getColumnFamilyStores())
c.forceBlockingFlush();
}
private ColumnFamilyStore createTestTable()
{
createTable("CREATE TABLE %s (" +
@ -165,6 +175,10 @@ public class PartitionRowAccountingTest extends CQLTester
final long insertTs = 1000L;
final long deleteTs = 2000L; // newer than insertTs, so the tombstone shadows the cells
flushAllToBaseline();
Memtable mtRetain = cfsRetain.getTracker().getView().getCurrentMemtable();
Memtable mtShadow = cfsShadow.getTracker().getView().getCurrentMemtable();
for (int ck = 0; ck < rows; ck++)
{
// retain path: write the row, then delete it -> the tombstone shadows existing (owned) cells
@ -176,6 +190,11 @@ public class PartitionRowAccountingTest extends CQLTester
QueryProcessor.executeInternal(wideInsert(tblShadow, ck, insertTs));
}
assertSame("retain memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtRetain, cfsRetain.getTracker().getView().getCurrentMemtable());
assertSame("removeShadowed memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtShadow, cfsShadow.getTracker().getView().getCurrentMemtable());
long onHeapRetain = ownsOnHeapNow(cfsRetain), onHeapShadow = ownsOnHeapNow(cfsShadow);
long offHeapRetain = ownsOffHeapNow(cfsRetain), offHeapShadow = ownsOffHeapNow(cfsShadow);
logger.info("retain-path onHeap=" + onHeapRetain + " offHeap=" + offHeapRetain +
@ -214,6 +233,10 @@ public class PartitionRowAccountingTest extends CQLTester
final long insertTs = 1000L;
final long deleteTs = 2000L; // newer than insertTs, so the tombstone shadows the collection cells
flushAllToBaseline();
Memtable mtRetain = cfsRetain.getTracker().getView().getCurrentMemtable();
Memtable mtShadow = cfsShadow.getTracker().getView().getCurrentMemtable();
for (int ck = 0; ck < rows; ck++)
{
// retain path: write the row (large collection), then delete it -> the tombstone shadows existing (owned)
@ -226,6 +249,11 @@ public class PartitionRowAccountingTest extends CQLTester
QueryProcessor.executeInternal(setInsert(tblShadow, ck, insertTs));
}
assertSame("retain memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtRetain, cfsRetain.getTracker().getView().getCurrentMemtable());
assertSame("removeShadowed memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtShadow, cfsShadow.getTracker().getView().getCurrentMemtable());
long onHeapRetain = ownsOnHeapNow(cfsRetain), onHeapShadow = ownsOnHeapNow(cfsShadow);
long offHeapRetain = ownsOffHeapNow(cfsRetain), offHeapShadow = ownsOffHeapNow(cfsShadow);
logger.info("collection retain-path onHeap=" + onHeapRetain + " offHeap=" + offHeapRetain +
@ -267,6 +295,10 @@ public class PartitionRowAccountingTest extends CQLTester
final long collectionDeleteTs = 1000L;
final long rowDeleteTs = 2000L; // newer, so the row tombstone supersedes the collection tombstone
flushAllToBaseline();
Memtable mtRetain = cfsRetain.getTracker().getView().getCurrentMemtable();
Memtable mtShadow = cfsShadow.getTracker().getView().getCurrentMemtable();
for (int ck = 0; ck < rows; ck++)
{
// retain path: write a collection tombstone (an owned complex deletion over an empty cell tree),
@ -279,6 +311,11 @@ public class PartitionRowAccountingTest extends CQLTester
QueryProcessor.executeInternal(collectionDelete(tblShadow, ck, collectionDeleteTs));
}
assertSame("retain memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtRetain, cfsRetain.getTracker().getView().getCurrentMemtable());
assertSame("removeShadowed memtable rolled (flushed) mid-test -- on-heap ownership measurement invalid",
mtShadow, cfsShadow.getTracker().getView().getCurrentMemtable());
long onHeapRetain = ownsOnHeapNow(cfsRetain), onHeapShadow = ownsOnHeapNow(cfsShadow);
logger.info("collection-tombstone retain-path onHeap=" + onHeapRetain +
"; removeShadowed-path onHeap=" + onHeapShadow);