Skip to content

Commit 9a534ba

Browse files
committed
Merge branch 'cassandra-5.0' into trunk
2 parents f0cb7f1 + 4091613 commit 9a534ba

File tree

5 files changed

+57
-6
lines changed

5 files changed

+57
-6
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ Merged from 4.1:
329329
* Enforce CQL message size limit on multiframe messages (CASSANDRA-20052)
330330
* Fix race condition in DecayingEstimatedHistogramReservoir during rescale (CASSANDRA-19365)
331331
Merged from 4.0:
332+
* Leveled Compaction doesn't validate maxBytesForLevel when the table is altered/created (CASSANDRA-20570)
332333
* Updated dtest-api to 0.0.18 and removed JMX-related classes that now live in the dtest-api (CASSANDRA-20884)
333334
* Fixed incorrect error message constant for keyspace name length validation (CASSANDRA-20915)
334335
* Prevent too long table names not fitting file names (CASSANDRA-20389)

src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.cassandra.db.compaction;
1919

2020
import java.util.*;
21+
import java.math.BigInteger;
2122

2223

2324
import com.google.common.annotations.VisibleForTesting;
@@ -43,6 +44,7 @@
4344
import org.apache.cassandra.io.sstable.format.SSTableReader;
4445

4546
import static org.apache.cassandra.config.CassandraRelevantProperties.TOLERATE_SSTABLE_SIZE;
47+
import static org.apache.cassandra.db.compaction.LeveledGenerations.MAX_LEVEL_COUNT;
4648

4749
public class LeveledCompactionStrategy extends AbstractCompactionStrategy
4850
{
@@ -569,10 +571,14 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
569571
{
570572
Map<String, String> uncheckedOptions = AbstractCompactionStrategy.validateOptions(options);
571573

574+
int ssSize;
575+
int fanoutSize;
576+
577+
// Validate the sstable_size option
572578
String size = options.containsKey(SSTABLE_SIZE_OPTION) ? options.get(SSTABLE_SIZE_OPTION) : "1";
573579
try
574580
{
575-
int ssSize = Integer.parseInt(size);
581+
ssSize = Integer.parseInt(size);
576582
if (ssSize < 1)
577583
{
578584
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", SSTABLE_SIZE_OPTION, ssSize));
@@ -589,15 +595,31 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
589595
String levelFanoutSize = options.containsKey(LEVEL_FANOUT_SIZE_OPTION) ? options.get(LEVEL_FANOUT_SIZE_OPTION) : String.valueOf(DEFAULT_LEVEL_FANOUT_SIZE);
590596
try
591597
{
592-
int fanoutSize = Integer.parseInt(levelFanoutSize);
598+
fanoutSize = Integer.parseInt(levelFanoutSize);
593599
if (fanoutSize < 1)
594600
{
595601
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", LEVEL_FANOUT_SIZE_OPTION, fanoutSize));
596602
}
597603
}
598604
catch (NumberFormatException ex)
599605
{
600-
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", size, LEVEL_FANOUT_SIZE_OPTION), ex);
606+
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", levelFanoutSize, LEVEL_FANOUT_SIZE_OPTION), ex);
607+
}
608+
609+
// Validate max Bytes for a level
610+
try
611+
{
612+
long maxSSTableSizeInBytes = Math.multiplyExact(ssSize, 1024L * 1024L); // Convert MB to Bytes
613+
BigInteger fanoutPower = BigInteger.valueOf(fanoutSize).pow(MAX_LEVEL_COUNT - 1);
614+
BigInteger maxBytes = fanoutPower.multiply(BigInteger.valueOf(maxSSTableSizeInBytes));
615+
BigInteger longMaxValue = BigInteger.valueOf(Long.MAX_VALUE);
616+
if (maxBytes.compareTo(longMaxValue) > 0)
617+
throw new ConfigurationException(String.format("At most %s bytes may be in a compaction level; " +
618+
"your maxSSTableSize must be absurdly high to compute %s", Long.MAX_VALUE, maxBytes));
619+
}
620+
catch (ArithmeticException ex)
621+
{
622+
throw new ConfigurationException(String.format("sstable_size_in_mb=%d is too large; resulting bytes exceed Long.MAX_VALUE (%d)", ssSize, Long.MAX_VALUE), ex);
601623
}
602624

603625
uncheckedOptions.remove(LEVEL_FANOUT_SIZE_OPTION);

test/unit/org/apache/cassandra/db/compaction/LeveledCompactionStrategyTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,24 @@ public void testReduceScopeL0L1() throws IOException
975975
}
976976
}
977977

978+
@Test()
979+
public void testInvalidFanoutAndSSTableSize()
980+
{
981+
try
982+
{
983+
Map<String, String> options = new HashMap<>();
984+
options.put("class", "LeveledCompactionStrategy");
985+
options.put("fanout_size", "90");
986+
options.put("sstable_size_in_mb", "1089");
987+
LeveledCompactionStrategy.validateOptions(options);
988+
Assert.fail("fanout_sizeed and sstable_size_in_mb are invalid, but did not throw ConfigurationException");
989+
}
990+
catch (ConfigurationException e)
991+
{
992+
assertTrue(e.getMessage().contains("your maxSSTableSize must be absurdly high to compute"));
993+
}
994+
}
995+
978996
@Test
979997
public void testReduceScopeL0()
980998
{

test/unit/org/apache/cassandra/schema/CreateTableValidationTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ public void testNonAlphanummericTableName() throws Throwable
134134
String.format("CREATE TABLE %s.\" \" (key int PRIMARY KEY, val int)", KEYSPACE));
135135
}
136136

137+
@Test
138+
public void testInvalidCompactionOptions()
139+
{
140+
expectedFailure(ConfigurationException.class, "CREATE TABLE %s (k int PRIMARY KEY, v int) WITH compaction = {'class': 'LeveledCompactionStrategy', 'fanout_size': '90', 'sstable_size_in_mb': '1089'}",
141+
"your maxSSTableSize must be absurdly high to compute");
142+
}
143+
137144
private void expectedFailure(final Class<? extends RequestValidationException> exceptionType, String statement, String errorMsg)
138145
{
139146

test/unit/org/apache/cassandra/utils/CassandraGenerators.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import com.google.common.collect.Sets;
5353

5454
import accord.utils.SortedArrays.SortedArrayList;
55-
import org.apache.cassandra.db.compaction.LeveledManifest;
5655
import org.apache.cassandra.schema.*;
5756
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
5857
import org.apache.cassandra.tcm.extensions.ExtensionKey;
@@ -143,6 +142,7 @@
143142
import static org.apache.cassandra.utils.Generators.TIMESTAMP_NANOS;
144143
import static org.apache.cassandra.utils.Generators.TINY_TIME_SPAN_NANOS;
145144
import static org.apache.cassandra.utils.Generators.directAndHeapBytes;
145+
import static org.junit.Assert.assertTrue;
146146

147147
public final class CassandraGenerators
148148
{
@@ -585,11 +585,14 @@ public static class CompactionParamsBuilder
585585
try
586586
{
587587
// see org.apache.cassandra.db.compaction.LeveledGenerations.MAX_LEVEL_COUNT for why 8 is hard coded here
588-
LeveledManifest.maxBytesForLevel(8, value, maxSSTableSizeInBytes);
588+
// LeveledManifest.maxBytesForLevel(8, value, maxSSTableSizeInBytes);
589+
options.put(LeveledCompactionStrategy.LEVEL_FANOUT_SIZE_OPTION, value.toString());
590+
LeveledCompactionStrategy.validateOptions(options);
589591
break; // value is good, keep it
590592
}
591-
catch (RuntimeException e)
593+
catch (ConfigurationException e)
592594
{
595+
assertTrue(e.getMessage().contains("your maxSSTableSize must be absurdly high to compute"));
593596
// this value is too large... lets shrink it
594597
if (value.intValue() == 1)
595598
throw new AssertionError("There is no possible fanout size that works with maxSSTableSizeInMB=" + maxSSTableSizeInMB);

0 commit comments

Comments
 (0)