From e4cdfc3a3ee1a7863508b61af485149f1e0d1853 Mon Sep 17 00:00:00 2001 From: Jeff Zhong <32740973+innovationb1ue@users.noreply.github.com> Date: Thu, 12 Mar 2026 23:13:07 +0800 Subject: [PATCH 1/2] CASSANDRA-20901 fix typos --- CHANGES.txt | 2 +- .../cql3/selection/ColumnFilterFactory.java | 2 +- .../TombstoneOverwhelmingException.java | 2 +- src/java/org/apache/cassandra/dht/Token.java | 2 +- .../apache/cassandra/gms/GossipDigestSyn.java | 16 ++--- .../gms/GossipDigestSynVerbHandler.java | 4 +- .../uncommitted/UncommittedTableData.java | 2 +- .../apache/cassandra/utils/MerkleTree.java | 2 +- .../ZstdDictionaryTrainerTest.java | 71 +++++++++++++++++++ .../cassandra/io/sstable/ScrubTest.java | 2 +- 10 files changed, 88 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 68e5778058f6..39b272e3063d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8097,7 +8097,7 @@ Merged from 0.8: * avoid preserving login information after client disconnects (CASSANDRA-1057) * prefer sun jdk to openjdk in debian init script (CASSANDRA-1174) - * detect partioner config changes between restarts and fail fast + * detect partitioner config changes between restarts and fail fast (CASSANDRA-1146) * use generation time to resolve node token reassignment disagreements (CASSANDRA-1118) diff --git a/src/java/org/apache/cassandra/cql3/selection/ColumnFilterFactory.java b/src/java/org/apache/cassandra/cql3/selection/ColumnFilterFactory.java index 63fa0520101e..9be171dbd356 100644 --- a/src/java/org/apache/cassandra/cql3/selection/ColumnFilterFactory.java +++ b/src/java/org/apache/cassandra/cql3/selection/ColumnFilterFactory.java @@ -27,7 +27,7 @@ /** * Factory for {@code ColumnFilter} instances. *

This class is used to abstract the fact that depending on the selection clause the {@code ColumnFilter} instances - * can be computed at prepartion time (if all the requested columns are known) or must be computed at execution time.

+ * can be computed at prepartition time (if all the requested columns are known) or must be computed at execution time.

*/ abstract class ColumnFilterFactory { diff --git a/src/java/org/apache/cassandra/db/filter/TombstoneOverwhelmingException.java b/src/java/org/apache/cassandra/db/filter/TombstoneOverwhelmingException.java index 200f94f80a3e..3bc99d2c90c3 100644 --- a/src/java/org/apache/cassandra/db/filter/TombstoneOverwhelmingException.java +++ b/src/java/org/apache/cassandra/db/filter/TombstoneOverwhelmingException.java @@ -31,7 +31,7 @@ public class TombstoneOverwhelmingException extends RejectException { public TombstoneOverwhelmingException(int numTombstones, String query, TableMetadata metadata, DecoratedKey lastPartitionKey, ClusteringPrefix lastClustering) { - super(String.format("Scanned over %d tombstones during query '%s' (last scanned row token was %s and partion key was (%s)); query aborted", + super(String.format("Scanned over %d tombstones during query '%s' (last scanned row token was %s and partitioner key was (%s)); query aborted", numTombstones, query, lastPartitionKey.getToken(), makePKString(metadata, lastPartitionKey.getKey(), lastClustering))); } diff --git a/src/java/org/apache/cassandra/dht/Token.java b/src/java/org/apache/cassandra/dht/Token.java index 9305b33af414..95e475631af2 100644 --- a/src/java/org/apache/cassandra/dht/Token.java +++ b/src/java/org/apache/cassandra/dht/Token.java @@ -301,7 +301,7 @@ public long getLongValue() * between this token and it in the token order. * * This is not possible for all token types, esp. for comparison-based - * tokens such as the LocalPartioner used for classic secondary indexes. + * tokens such as the LocalPartitioner used for classic secondary indexes. * * Used to avoid clashes between nodes in separate datacentres trying to * use the same token via the token allocation algorithm, as well as in diff --git a/src/java/org/apache/cassandra/gms/GossipDigestSyn.java b/src/java/org/apache/cassandra/gms/GossipDigestSyn.java index b93fa25ca739..5328d6fbf512 100644 --- a/src/java/org/apache/cassandra/gms/GossipDigestSyn.java +++ b/src/java/org/apache/cassandra/gms/GossipDigestSyn.java @@ -38,14 +38,14 @@ public class GossipDigestSyn public static final IVersionedSerializer serializer = new GossipDigestSynSerializer(); final String clusterId; - final String partioner; + final String partitioner; final int metadataId; final List gDigests; - public GossipDigestSyn(String clusterId, String partioner, int metadataId, List gDigests) + public GossipDigestSyn(String clusterId, String partitioner, int metadataId, List gDigests) { this.clusterId = clusterId; - this.partioner = partioner; + this.partitioner = partitioner; this.metadataId = metadataId; this.gDigests = gDigests; } @@ -88,7 +88,7 @@ class GossipDigestSynSerializer implements IVersionedSerializer public void serialize(GossipDigestSyn gDigestSynMessage, DataOutputPlus out, int version) throws IOException { out.writeUTF(gDigestSynMessage.clusterId); - out.writeUTF(gDigestSynMessage.partioner); + out.writeUTF(gDigestSynMessage.partitioner); if (version >= MessagingService.VERSION_51) out.writeUnsignedVInt32(gDigestSynMessage.metadataId); GossipDigestSerializationHelper.serialize(gDigestSynMessage.gDigests, out, version); @@ -97,19 +97,19 @@ public void serialize(GossipDigestSyn gDigestSynMessage, DataOutputPlus out, int public GossipDigestSyn deserialize(DataInputPlus in, int version) throws IOException { String clusterId = in.readUTF(); - String partioner = null; - partioner = in.readUTF(); + String partitioner = null; + partitioner = in.readUTF(); int metadataId = version >= MessagingService.VERSION_51 ? in.readUnsignedVInt32() : ClusterMetadata.EMPTY_METADATA_IDENTIFIER; List gDigests = GossipDigestSerializationHelper.deserialize(in, version); - return new GossipDigestSyn(clusterId, partioner, metadataId, gDigests); + return new GossipDigestSyn(clusterId, partitioner, metadataId, gDigests); } public long serializedSize(GossipDigestSyn syn, int version) { long size = TypeSizes.sizeof(syn.clusterId); - size += TypeSizes.sizeof(syn.partioner); + size += TypeSizes.sizeof(syn.partitioner); if (version >= MessagingService.VERSION_51) size += TypeSizes.sizeofUnsignedVInt(syn.metadataId); size += GossipDigestSerializationHelper.serializedSize(syn.gDigests, version); diff --git a/src/java/org/apache/cassandra/gms/GossipDigestSynVerbHandler.java b/src/java/org/apache/cassandra/gms/GossipDigestSynVerbHandler.java index 93a8252a983c..6ecd8deb2e15 100644 --- a/src/java/org/apache/cassandra/gms/GossipDigestSynVerbHandler.java +++ b/src/java/org/apache/cassandra/gms/GossipDigestSynVerbHandler.java @@ -58,9 +58,9 @@ public void doVerb(Message message) return; } - if (gDigestMessage.partioner != null && !gDigestMessage.partioner.equals(DatabaseDescriptor.getPartitionerName())) + if (gDigestMessage.partitioner != null && !gDigestMessage.partitioner.equals(DatabaseDescriptor.getPartitionerName())) { - logger.warn("Partitioner mismatch from {} {}!={}", from, gDigestMessage.partioner, DatabaseDescriptor.getPartitionerName()); + logger.warn("Partitioner mismatch from {} {}!={}", from, gDigestMessage.partitioner, DatabaseDescriptor.getPartitionerName()); return; } diff --git a/src/java/org/apache/cassandra/service/paxos/uncommitted/UncommittedTableData.java b/src/java/org/apache/cassandra/service/paxos/uncommitted/UncommittedTableData.java index d55aaae39a72..39cac1cb4b50 100644 --- a/src/java/org/apache/cassandra/service/paxos/uncommitted/UncommittedTableData.java +++ b/src/java/org/apache/cassandra/service/paxos/uncommitted/UncommittedTableData.java @@ -143,7 +143,7 @@ protected PaxosKeyState computeNext() } PaxosKeyState next = peeking.next(); - // If repairing a table with a partioner different from IPartitioner.global(), such as the distributed + // If repairing a table with a partitioner different from IPartitioner.global(), such as the distributed // metadata log table, we don't filter paxos keys outside the data range of the repair. Instead, we // repair everything present for that table. Replicas of the distributed log table (i.e. CMS members) // always replicate the entire table, so this is not much of an issue at present. diff --git a/src/java/org/apache/cassandra/utils/MerkleTree.java b/src/java/org/apache/cassandra/utils/MerkleTree.java index b6b0141db164..d3efea8d9056 100644 --- a/src/java/org/apache/cassandra/utils/MerkleTree.java +++ b/src/java/org/apache/cassandra/utils/MerkleTree.java @@ -1531,7 +1531,7 @@ public static int estimatedMaxDepthForBytes(IPartitioner partitioner, long numBy Inner inner = new OnHeapInner(partitioner.getMinimumToken(), left, right); inner.fillInnerHashes(); - // Some partioners have variable token sizes, try to estimate as close as we can by using the same + // Some partitioners have variable token sizes, try to estimate as close as we can by using the same // heap estimate as the memtables use. long innerTokenSize = ObjectSizes.measureDeep(partitioner.getMinimumToken()); long realInnerTokenSize = partitioner.getMinimumToken().getHeapSize(); diff --git a/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java b/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java index 5e7f526012ca..e645e2db86c7 100644 --- a/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java +++ b/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java @@ -598,6 +598,77 @@ private void addSampleData(int totalSize) } } + @Test + public void testTrainerWithExcessiveMaxTotalSampleSizeHandlesOOM() + { + // Create a subclass that simulates OOM during ZstdDictTrainer creation + ZstdDictionaryTrainer oomTrainer = new ZstdDictionaryTrainer(TEST_KEYSPACE, TEST_TABLE, COMPRESSION_LEVEL) + { + @Override + public void reset(CompressionDictionaryTrainingConfig trainingConfig) + { + // Simulate the OOM handling path by directly throwing the wrapped exception + // that would be thrown when ZstdDictTrainer allocation fails + throw new IllegalStateException( + String.format("Unable to allocate %s direct buffer for dictionary training. " + + "Consider reducing max total sample size or increasing JVM max direct memory (-XX:MaxDirectMemorySize).", + "8 EiB"), + new OutOfMemoryError("Direct buffer memory")); + } + }; + + AtomicReference localCallbackResult = new AtomicReference<>(); + oomTrainer.setDictionaryTrainedListener(localCallbackResult::set); + + CompressionDictionaryTrainingConfig config = CompressionDictionaryTrainingConfig.builder() + .maxDictionarySize(1024) + .maxTotalSampleSize(10 * 1024) + .build(); + + // Attempting to start should return false and set status to FAILED + assertThat(oomTrainer.start(config)) + .as("Start should return false when OOM occurs during trainer allocation") + .isFalse(); + + // Verify the trainer is in FAILED state + assertThat(oomTrainer.getTrainingState().getStatus()) + .as("Status should be FAILED after OOM during start") + .isEqualTo(TrainingStatus.FAILED); + + assertThat(oomTrainer.getTrainingState().getFailureMessage()) + .as("Failure message should contain information about allocation failure") + .contains("Failed to create ZstdDictTrainer") + .contains("Unable to allocate") + .contains("direct buffer for dictionary training"); + + // Clean up + oomTrainer.close(); + } + + @Test + public void testTrainerResetWithOOMThrowsIllegalStateException() + { + // Start the trainer first with a valid config + trainer.start(testConfig); + + // Verify the OOM handling by directly testing the exception wrapping logic + // We use reflection to simulate the OOM scenario in the reset() method + assertThatThrownBy(() -> { + // Simulate the exact exception that would be thrown from reset() + // when ZstdDictTrainer allocation fails + throw new IllegalStateException( + String.format("Unable to allocate %s direct buffer for dictionary training. " + + "Consider reducing max total sample size or increasing JVM max direct memory (-XX:MaxDirectMemorySize).", + "8 EiB"), + new OutOfMemoryError("Direct buffer memory")); + }) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Unable to allocate") + .hasMessageContaining("direct buffer for dictionary training") + .hasMessageContaining("Consider reducing max total sample size or increasing JVM max direct memory") + .hasCauseInstanceOf(OutOfMemoryError.class); + } + @Test public void testStatisticsMethods() { diff --git a/test/unit/org/apache/cassandra/io/sstable/ScrubTest.java b/test/unit/org/apache/cassandra/io/sstable/ScrubTest.java index f641be414908..939cb71bf234 100644 --- a/test/unit/org/apache/cassandra/io/sstable/ScrubTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/ScrubTest.java @@ -412,7 +412,7 @@ public void testScrubOneRowWithCorruptedKey() throws IOException, ConfigurationE if (BigFormat.is(sstable.descriptor.getFormat())) assertOrderedAll(cfs, 4); else if (BtiFormat.is(sstable.descriptor.getFormat())) - // For Trie format we won't be able to recover the damaged partition key (partion index doesn't store the whole key) + // For Trie format we won't be able to recover the damaged partition key (partitioner index doesn't store the whole key) assertOrderedAll(cfs, 3); else throw Util.testMustBeImplementedForSSTableFormat(); From ca85b425217208c0601b76edf200228822559b68 Mon Sep 17 00:00:00 2001 From: Jeff Zhong <32740973+innovationb1ue@users.noreply.github.com> Date: Thu, 12 Mar 2026 23:26:04 +0800 Subject: [PATCH 2/2] CASSANDRA-20901 fix typos --- .../ZstdDictionaryTrainerTest.java | 71 ------------------- 1 file changed, 71 deletions(-) diff --git a/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java b/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java index e645e2db86c7..5e7f526012ca 100644 --- a/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java +++ b/test/unit/org/apache/cassandra/db/compression/ZstdDictionaryTrainerTest.java @@ -598,77 +598,6 @@ private void addSampleData(int totalSize) } } - @Test - public void testTrainerWithExcessiveMaxTotalSampleSizeHandlesOOM() - { - // Create a subclass that simulates OOM during ZstdDictTrainer creation - ZstdDictionaryTrainer oomTrainer = new ZstdDictionaryTrainer(TEST_KEYSPACE, TEST_TABLE, COMPRESSION_LEVEL) - { - @Override - public void reset(CompressionDictionaryTrainingConfig trainingConfig) - { - // Simulate the OOM handling path by directly throwing the wrapped exception - // that would be thrown when ZstdDictTrainer allocation fails - throw new IllegalStateException( - String.format("Unable to allocate %s direct buffer for dictionary training. " + - "Consider reducing max total sample size or increasing JVM max direct memory (-XX:MaxDirectMemorySize).", - "8 EiB"), - new OutOfMemoryError("Direct buffer memory")); - } - }; - - AtomicReference localCallbackResult = new AtomicReference<>(); - oomTrainer.setDictionaryTrainedListener(localCallbackResult::set); - - CompressionDictionaryTrainingConfig config = CompressionDictionaryTrainingConfig.builder() - .maxDictionarySize(1024) - .maxTotalSampleSize(10 * 1024) - .build(); - - // Attempting to start should return false and set status to FAILED - assertThat(oomTrainer.start(config)) - .as("Start should return false when OOM occurs during trainer allocation") - .isFalse(); - - // Verify the trainer is in FAILED state - assertThat(oomTrainer.getTrainingState().getStatus()) - .as("Status should be FAILED after OOM during start") - .isEqualTo(TrainingStatus.FAILED); - - assertThat(oomTrainer.getTrainingState().getFailureMessage()) - .as("Failure message should contain information about allocation failure") - .contains("Failed to create ZstdDictTrainer") - .contains("Unable to allocate") - .contains("direct buffer for dictionary training"); - - // Clean up - oomTrainer.close(); - } - - @Test - public void testTrainerResetWithOOMThrowsIllegalStateException() - { - // Start the trainer first with a valid config - trainer.start(testConfig); - - // Verify the OOM handling by directly testing the exception wrapping logic - // We use reflection to simulate the OOM scenario in the reset() method - assertThatThrownBy(() -> { - // Simulate the exact exception that would be thrown from reset() - // when ZstdDictTrainer allocation fails - throw new IllegalStateException( - String.format("Unable to allocate %s direct buffer for dictionary training. " + - "Consider reducing max total sample size or increasing JVM max direct memory (-XX:MaxDirectMemorySize).", - "8 EiB"), - new OutOfMemoryError("Direct buffer memory")); - }) - .isInstanceOf(IllegalStateException.class) - .hasMessageContaining("Unable to allocate") - .hasMessageContaining("direct buffer for dictionary training") - .hasMessageContaining("Consider reducing max total sample size or increasing JVM max direct memory") - .hasCauseInstanceOf(OutOfMemoryError.class); - } - @Test public void testStatisticsMethods() {