1818package org .apache .cassandra .db .compaction ;
1919
2020import java .util .*;
21+ import java .math .BigInteger ;
2122
2223
2324import com .google .common .annotations .VisibleForTesting ;
4344import org .apache .cassandra .io .sstable .format .SSTableReader ;
4445
4546import static org .apache .cassandra .config .CassandraRelevantProperties .TOLERATE_SSTABLE_SIZE ;
47+ import static org .apache .cassandra .db .compaction .LeveledGenerations .MAX_LEVEL_COUNT ;
4648
4749public 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 );
0 commit comments