This is an automated email from the ASF dual-hosted git repository. maedhroz pushed a commit to branch cep-45-mutation-tracking in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 4bbb14c179da9770a20e84b815d3820d4a5340c0 Author: Abe Ratnofsky <a...@aber.io> AuthorDate: Fri Sep 5 15:56:00 2025 -0400 Fix loss of isRepaired StatsMetadata on compaction race Found via MultiNodeTableWalkWithMutationTrackingTest after ~hundreds of seeds. java.lang.IllegalArgumentException: Cannot compact repaired and unrepaired sstables at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143) at org.apache.cassandra.db.compaction.AbstractCompactionTask.validateSSTables(AbstractCompactionTask.java:84) at org.apache.cassandra.db.compaction.AbstractCompactionTask.<init>(AbstractCompactionTask.java:60) at org.apache.cassandra.db.compaction.CompactionTask.<init>(CompactionTask.java:79) at org.apache.cassandra.db.compaction.CompactionTask.<init>(CompactionTask.java:74) at org.apache.cassandra.db.compaction.LeveledCompactionTask.<init>(LeveledCompactionTask.java:39) at org.apache.cassandra.db.compaction.LeveledCompactionStrategy.getMaximalTasks(LeveledCompactionStrategy.java:192) at org.apache.cassandra.db.compaction.CompactionStrategyHolder.getMaximalTasks(CompactionStrategyHolder.java:121) patch by Abe Ratnofsky; reviewed by Caleb Rackliffe for CASSANDRA-20830 --- .../cassandra/io/sstable/format/SSTableWriter.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java index d1a2df907c..0190282fc7 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableWriter.java @@ -401,13 +401,31 @@ public abstract class SSTableWriter extends SSTable implements Transactional protected void doPrepare() { transactionals.get().forEach(Transactional::prepareToCommit); - new StatsComponent(finalizeMetadata()).save(descriptor); + Map<MetadataType, MetadataComponent> metadata = finalizeMetadata(); + new StatsComponent(metadata).save(descriptor); // save the table of components TOCComponent.updateTOC(descriptor, components); if (openResult) + { finalReader = openFinal(SSTableReader.OpenReason.NORMAL); + + /* + When we open above, we re-finalize metadata and may be durably reconciled, but this is after + StatsComponent is saved, so the next reload from disk loses the reconciliation update. We need to save + again to ensure the descriptor file matches what's in memory. + + Could move this to the post-flush compaction, but then we couldn't flush directly into the repaired set. + Or see if we can open before the first save, so we never have to write stats to disk twice. + */ + StatsMetadata stale = ((StatsMetadata) metadata.get(MetadataType.STATS)); + if (finalReader.getSSTableMetadata().repairedAt != stale.repairedAt) + { + metadata.put(MetadataType.STATS, finalReader.getSSTableMetadata()); + new StatsComponent(metadata).save(descriptor); + } + } } protected Throwable doCommit(Throwable accumulate) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org