Skip to content

Commit e4ea61c

Browse files
committed
Merge branch 'cassandra-4.0' into cassandra-4.1
2 parents 7b312d4 + 61014f2 commit e4ea61c

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* ReadCommandController should close fast to avoid deadlock when building secondary index (CASSANDRA-19564)
33
* Redact security-sensitive information in system_views.settings (CASSANDRA-20856)
44
Merged from 4.0:
5+
* Leveled Compaction doesn't validate maxBytesForLevel when the table is altered/created (CASSANDRA-20570)
56
* Updated dtest-api to 0.0.18 and removed JMX-related classes that now live in the dtest-api (CASSANDRA-20884)
67
* Fixed incorrect error message constant for keyspace name length validation (CASSANDRA-20915)
78
* update shaded cassandra-driver-core to 3.11.5 (CASSANDRA-20904)

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

Lines changed: 26 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,8 @@
4344
import org.apache.cassandra.io.sstable.ISSTableScanner;
4445
import org.apache.cassandra.io.sstable.format.SSTableReader;
4546

47+
import static org.apache.cassandra.db.compaction.LeveledGenerations.MAX_LEVEL_COUNT;
48+
4649
public class LeveledCompactionStrategy extends AbstractCompactionStrategy
4750
{
4851
private static final Logger logger = LoggerFactory.getLogger(LeveledCompactionStrategy.class);
@@ -565,10 +568,14 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
565568
{
566569
Map<String, String> uncheckedOptions = AbstractCompactionStrategy.validateOptions(options);
567570

571+
int ssSize;
572+
int fanoutSize;
573+
574+
// Validate the sstable_size option
568575
String size = options.containsKey(SSTABLE_SIZE_OPTION) ? options.get(SSTABLE_SIZE_OPTION) : "1";
569576
try
570577
{
571-
int ssSize = Integer.parseInt(size);
578+
ssSize = Integer.parseInt(size);
572579
if (ssSize < 1)
573580
{
574581
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", SSTABLE_SIZE_OPTION, ssSize));
@@ -585,15 +592,31 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
585592
String levelFanoutSize = options.containsKey(LEVEL_FANOUT_SIZE_OPTION) ? options.get(LEVEL_FANOUT_SIZE_OPTION) : String.valueOf(DEFAULT_LEVEL_FANOUT_SIZE);
586593
try
587594
{
588-
int fanoutSize = Integer.parseInt(levelFanoutSize);
595+
fanoutSize = Integer.parseInt(levelFanoutSize);
589596
if (fanoutSize < 1)
590597
{
591598
throw new ConfigurationException(String.format("%s must be larger than 0, but was %s", LEVEL_FANOUT_SIZE_OPTION, fanoutSize));
592599
}
593600
}
594601
catch (NumberFormatException ex)
595602
{
596-
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", size, LEVEL_FANOUT_SIZE_OPTION), ex);
603+
throw new ConfigurationException(String.format("%s is not a parsable int (base10) for %s", levelFanoutSize, LEVEL_FANOUT_SIZE_OPTION), ex);
604+
}
605+
606+
// Validate max Bytes for a level
607+
try
608+
{
609+
long maxSSTableSizeInBytes = Math.multiplyExact(ssSize, 1024L * 1024L); // Convert MB to Bytes
610+
BigInteger fanoutPower = BigInteger.valueOf(fanoutSize).pow(MAX_LEVEL_COUNT - 1);
611+
BigInteger maxBytes = fanoutPower.multiply(BigInteger.valueOf(maxSSTableSizeInBytes));
612+
BigInteger longMaxValue = BigInteger.valueOf(Long.MAX_VALUE);
613+
if (maxBytes.compareTo(longMaxValue) > 0)
614+
throw new ConfigurationException(String.format("At most %s bytes may be in a compaction level; " +
615+
"your maxSSTableSize must be absurdly high to compute %s", Long.MAX_VALUE, maxBytes));
616+
}
617+
catch (ArithmeticException ex)
618+
{
619+
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);
597620
}
598621

599622
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
@@ -955,6 +955,24 @@ public void testReduceScopeL0L1() throws IOException
955955
}
956956
}
957957

958+
@Test()
959+
public void testInvalidFanoutAndSSTableSize()
960+
{
961+
try
962+
{
963+
Map<String, String> options = new HashMap<>();
964+
options.put("class", "LeveledCompactionStrategy");
965+
options.put("fanout_size", "90");
966+
options.put("sstable_size_in_mb", "1089");
967+
LeveledCompactionStrategy.validateOptions(options);
968+
Assert.fail("fanout_sizeed and sstable_size_in_mb are invalid, but did not throw ConfigurationException");
969+
}
970+
catch (ConfigurationException e)
971+
{
972+
assertTrue(e.getMessage().contains("your maxSSTableSize must be absurdly high to compute"));
973+
}
974+
}
975+
958976
@Test
959977
public void testReduceScopeL0()
960978
{

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.cassandra.cql3.QueryOptions;
2929
import org.apache.cassandra.exceptions.ConfigurationException;
3030
import org.apache.cassandra.exceptions.InvalidRequestException;
31+
import org.apache.cassandra.exceptions.RequestValidationException;
3132
import org.apache.cassandra.transport.Message;
3233
import org.apache.cassandra.transport.ProtocolVersion;
3334
import org.apache.cassandra.transport.SimpleClient;
@@ -203,9 +204,22 @@ public void testNonAlphanummericTableName() throws Throwable
203204
String.format("CREATE TABLE %s.\" \" (key int PRIMARY KEY, val int)", KEYSPACE));
204205
}
205206

206-
private void expectedFailure(String statement, String errorMsg)
207+
@Test
208+
public void testInvalidCompactionOptions()
209+
{
210+
expectedFailure(ConfigurationException.class, "CREATE TABLE %s (k int PRIMARY KEY, v int) WITH compaction = {'class': 'LeveledCompactionStrategy', 'fanout_size': '90', 'sstable_size_in_mb': '1089'}",
211+
"your maxSSTableSize must be absurdly high to compute");
212+
}
213+
214+
private void expectedFailure(final Class<? extends RequestValidationException> exceptionType, String statement, String errorMsg)
207215
{
208216

217+
assertThatExceptionOfType(exceptionType)
218+
.isThrownBy(() -> createTableMayThrow(statement)) .withMessageContaining(errorMsg);
219+
}
220+
221+
private void expectedFailure(String statement, String errorMsg)
222+
{
209223
assertThatExceptionOfType(InvalidRequestException.class)
210224
.isThrownBy(() -> createTableMayThrow(statement)) .withMessageContaining(errorMsg);
211225
}

0 commit comments

Comments
 (0)