Skip to content

Commit 4091613

Browse files
committed
Merge branch 'cassandra-4.1' into cassandra-5.0
2 parents 5ea935d + e4ea61c commit 4091613

File tree

4 files changed

+59
-4
lines changed

4 files changed

+59
-4
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Merged from 4.0:
1717
Merged from 4.1:
1818
* Redact security-sensitive information in system_views.settings (CASSANDRA-20856)
1919
Merged from 4.0:
20+
* Leveled Compaction doesn't validate maxBytesForLevel when the table is altered/created (CASSANDRA-20570)
2021
* Fixed incorrect error message constant for keyspace name length validation (CASSANDRA-20915)
2122
* Prevent too long table names not fitting file names (CASSANDRA-20389)
2223
* Update Jackson to 2.19.2 (CASSANDRA-20848)

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
{
@@ -568,10 +570,14 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
568570
{
569571
Map<String, String> uncheckedOptions = AbstractCompactionStrategy.validateOptions(options);
570572

573+
int ssSize;
574+
int fanoutSize;
575+
576+
// Validate the sstable_size option
571577
String size = options.containsKey(SSTABLE_SIZE_OPTION) ? options.get(SSTABLE_SIZE_OPTION) : "1";
572578
try
573579
{
574-
int ssSize = Integer.parseInt(size);
580+
ssSize = Integer.parseInt(size);
575581
if (ssSize < 1)
576582
{
577583
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", SSTABLE_SIZE_OPTION, ssSize));
@@ -588,15 +594,31 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
588594
String levelFanoutSize = options.containsKey(LEVEL_FANOUT_SIZE_OPTION) ? options.get(LEVEL_FANOUT_SIZE_OPTION) : String.valueOf(DEFAULT_LEVEL_FANOUT_SIZE);
589595
try
590596
{
591-
int fanoutSize = Integer.parseInt(levelFanoutSize);
597+
fanoutSize = Integer.parseInt(levelFanoutSize);
592598
if (fanoutSize < 1)
593599
{
594600
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", LEVEL_FANOUT_SIZE_OPTION, fanoutSize));
595601
}
596602
}
597603
catch (NumberFormatException ex)
598604
{
599-
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", size, LEVEL_FANOUT_SIZE_OPTION), ex);
605+
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", levelFanoutSize, LEVEL_FANOUT_SIZE_OPTION), ex);
606+
}
607+
608+
// Validate max Bytes for a level
609+
try
610+
{
611+
long maxSSTableSizeInBytes = Math.multiplyExact(ssSize, 1024L * 1024L); // Convert MB to Bytes
612+
BigInteger fanoutPower = BigInteger.valueOf(fanoutSize).pow(MAX_LEVEL_COUNT - 1);
613+
BigInteger maxBytes = fanoutPower.multiply(BigInteger.valueOf(maxSSTableSizeInBytes));
614+
BigInteger longMaxValue = BigInteger.valueOf(Long.MAX_VALUE);
615+
if (maxBytes.compareTo(longMaxValue) > 0)
616+
throw new ConfigurationException(String.format("At most %s bytes may be in a compaction level; " +
617+
"your maxSSTableSize must be absurdly high to compute %s", Long.MAX_VALUE, maxBytes));
618+
}
619+
catch (ArithmeticException ex)
620+
{
621+
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);
600622
}
601623

602624
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
@@ -964,6 +964,24 @@ public void testReduceScopeL0L1() throws IOException
964964
}
965965
}
966966

967+
@Test()
968+
public void testInvalidFanoutAndSSTableSize()
969+
{
970+
try
971+
{
972+
Map<String, String> options = new HashMap<>();
973+
options.put("class", "LeveledCompactionStrategy");
974+
options.put("fanout_size", "90");
975+
options.put("sstable_size_in_mb", "1089");
976+
LeveledCompactionStrategy.validateOptions(options);
977+
Assert.fail("fanout_sizeed and sstable_size_in_mb are invalid, but did not throw ConfigurationException");
978+
}
979+
catch (ConfigurationException e)
980+
{
981+
assertTrue(e.getMessage().contains("your maxSSTableSize must be absurdly high to compute"));
982+
}
983+
}
984+
967985
@Test
968986
public void testReduceScopeL0()
969987
{

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.cassandra.cql3.CQLTester;
2222
import org.apache.cassandra.exceptions.ConfigurationException;
2323
import org.apache.cassandra.exceptions.InvalidRequestException;
24+
import org.apache.cassandra.exceptions.RequestValidationException;
2425

2526
import org.junit.Test;
2627

@@ -143,9 +144,22 @@ public void testNonAlphanummericTableName() throws Throwable
143144
String.format("CREATE TABLE %s.\" \" (key int PRIMARY KEY, val int)", KEYSPACE));
144145
}
145146

146-
private void expectedFailure(String statement, String errorMsg)
147+
@Test
148+
public void testInvalidCompactionOptions()
149+
{
150+
expectedFailure(ConfigurationException.class, "CREATE TABLE %s (k int PRIMARY KEY, v int) WITH compaction = {'class': 'LeveledCompactionStrategy', 'fanout_size': '90', 'sstable_size_in_mb': '1089'}",
151+
"your maxSSTableSize must be absurdly high to compute");
152+
}
153+
154+
private void expectedFailure(final Class<? extends RequestValidationException> exceptionType, String statement, String errorMsg)
147155
{
148156

157+
assertThatExceptionOfType(exceptionType)
158+
.isThrownBy(() -> createTableMayThrow(statement)) .withMessageContaining(errorMsg);
159+
}
160+
161+
private void expectedFailure(String statement, String errorMsg)
162+
{
149163
assertThatExceptionOfType(InvalidRequestException.class)
150164
.isThrownBy(() -> createTableMayThrow(statement)) .withMessageContaining(errorMsg);
151165
}

0 commit comments

Comments
 (0)