Skip to content

Commit 3386599

Browse files
committed
(CASSANDRA-20398) Validating TARGET_SSTABLE_SIZE_OPTION and MIN_SSTABLE_SIZE_OPTION
The values were getting truncated resulting in unexpected output. patch by Pranav Shenoy; reviewed by Claude Warren for CASSANDRA-20398
1 parent b7f8f69 commit 3386599

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

src/java/org/apache/cassandra/db/compaction/unified/Controller.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -518,14 +518,20 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
518518
{
519519
try
520520
{
521-
targetSSTableSize = FBUtilities.parseHumanReadableBytes(s);
522-
if (targetSSTableSize < MIN_TARGET_SSTABLE_SIZE)
521+
double targetSize = FBUtilities.parseHumanReadable(s, null, "B");
522+
if (targetSize >= Long.MAX_VALUE) {
523+
throw new ConfigurationException(String.format("%s %s is out of range of Long.",
524+
TARGET_SSTABLE_SIZE_OPTION,
525+
s));
526+
}
527+
if (targetSize < MIN_TARGET_SSTABLE_SIZE)
523528
{
524529
throw new ConfigurationException(String.format("%s %s is not acceptable, size must be at least %s",
525530
TARGET_SSTABLE_SIZE_OPTION,
526531
s,
527532
FBUtilities.prettyPrintMemory(MIN_TARGET_SSTABLE_SIZE)));
528533
}
534+
targetSSTableSize = (long) Math.ceil(targetSize);
529535
}
530536
catch (NumberFormatException e)
531537
{
@@ -622,12 +628,12 @@ public static Map<String, String> validateOptions(Map<String, String> options) t
622628
if (sizeInBytes < 0)
623629
throw new ConfigurationException(String.format("Invalid configuration, %s should be greater than or equal to 0 (zero)",
624630
MIN_SSTABLE_SIZE_OPTION));
625-
int limit = (int) Math.ceil(targetSSTableSize * INVERSE_SQRT_2);
631+
long limit = (long) Math.ceil(targetSSTableSize * INVERSE_SQRT_2);
626632
if (sizeInBytes >= limit)
627-
throw new ConfigurationException(String.format("Invalid configuration, %s (%s) should be less than the target size minimum: %s",
633+
throw new ConfigurationException(String.format("Invalid configuration, %s (%s) should be less than 70%% of the targetSSTableSize (%s)",
628634
MIN_SSTABLE_SIZE_OPTION,
629635
FBUtilities.prettyPrintMemory(sizeInBytes),
630-
FBUtilities.prettyPrintMemory(limit)));
636+
FBUtilities.prettyPrintMemory(targetSSTableSize)));
631637
}
632638
catch (NumberFormatException e)
633639
{

test/unit/org/apache/cassandra/db/compaction/unified/ControllerTest.java

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,64 @@ public void testValidateOptionsIntegers()
121121
testValidateOptions(true);
122122
}
123123

124+
public void targetSSTableSizeValidator(String inputSize)
125+
{
126+
Map<String, String> options = new HashMap<>();
127+
options.putIfAbsent(Controller.TARGET_SSTABLE_SIZE_OPTION, inputSize);
128+
assertThatExceptionOfType(ConfigurationException.class)
129+
.describedAs("Should have thrown a ConfigurationException when target_sstable_size is greater than Long.MAX_VALUE")
130+
.isThrownBy(() -> Controller.validateOptions(options))
131+
.withMessageContaining(format("target_sstable_size %s is out of range of Long.", inputSize));
132+
}
133+
134+
@Test
135+
public void testCassandra20398Values()
136+
{
137+
//TARGET_SSTABLE_SIZE_OPTION = 12E899, the value reported in CASSANDRA-20398
138+
String inputSize = "12E899 B";
139+
targetSSTableSizeValidator(inputSize);
140+
}
141+
142+
@Test
143+
public void testValidateOptionsTargetSSTableSizeGTLongMax()
144+
{
145+
//TARGET_SSTABLE_SIZE_OPTION > LONG.MAX_VALUE
146+
// the inputSize is Long.MAX_VALUE + 100
147+
String inputSize = "9223372036854775907 B";
148+
targetSSTableSizeValidator(inputSize);
149+
}
150+
151+
@Test
152+
public void testValidateOptionsTargetSSTableSizeLTMinTargetSize()
153+
{
154+
// TARGET_SSTABLE_SIZE_OPTION < Default MIN_TARGET_SSTABLE_SIZE (1048576)
155+
Map<String, String> options = new HashMap<>();
156+
String inputSize = "1048000 B";
157+
options.putIfAbsent(Controller.TARGET_SSTABLE_SIZE_OPTION, inputSize);
158+
assertThatExceptionOfType(ConfigurationException.class)
159+
.describedAs("Should have thrown a ConfigurationException when target_sstable_size is less than default MIN_TARGET_SSTABLE_SIZE")
160+
.isThrownBy(() -> Controller.validateOptions(options))
161+
.withMessageContaining(format("target_sstable_size %s is not acceptable, size must be at least %s", inputSize, FBUtilities.prettyPrintMemory(Controller.MIN_TARGET_SSTABLE_SIZE)));
162+
}
163+
164+
@Test
165+
public void testValidateOptionsTargetSSTableSizeGTIntMax()
166+
{
167+
//TEST 4: Verifying if TARGET_SSTABLE_SIZE_OPTION (3650722199) < MIN_TARGET_SSTABLE_SIZE (2581450423)
168+
// Previously, TARGET_SSTABLE_SIZE_OPTION * 0.7 was stored as Integer which would 3650722199 * 0.7 = 2147483647
169+
// By storing it in a Long, 3650722199 * 0.7 = 2581450424. If TARGET_SSTABLE_SIZE_OPTION * 0.7 is truncated,
170+
//this test case will fail
171+
try
172+
{
173+
Map<String, String> options = new HashMap<>();
174+
options.putIfAbsent(Controller.TARGET_SSTABLE_SIZE_OPTION, "3650722199 B");
175+
options.putIfAbsent(Controller.MIN_SSTABLE_SIZE_OPTION, "2581450423 B");
176+
Controller.validateOptions(options);
177+
} catch(ConfigurationException e) {
178+
fail("3650722199 * 0.7 got truncated. " + e.getMessage());
179+
}
180+
}
181+
124182
void testValidateOptions(boolean useIntegers)
125183
{
126184
Map<String, String> options = new HashMap<>();
@@ -579,7 +637,7 @@ public void testMinSSTableSize()
579637
assertThatExceptionOfType(ConfigurationException.class)
580638
.describedAs("Should have thrown a ConfigurationException when min_sstable_size is greater than target_sstable_size")
581639
.isThrownBy(() -> Controller.validateOptions(options))
582-
.withMessageContaining(format("less than the target size minimum: %s", FBUtilities.prettyPrintMemory(limit)));
640+
.withMessageContaining(format("Invalid configuration, %s (%s) should be less than 70%% of the targetSSTableSize (%s)", Controller.MIN_SSTABLE_SIZE_OPTION, FBUtilities.prettyPrintMemory(limit+1), FBUtilities.prettyPrintMemory(Controller.DEFAULT_TARGET_SSTABLE_SIZE)));
583641

584642
// test min < configured target table size * INV_SQRT_2
585643
limit = (int) Math.ceil(Controller.MIN_TARGET_SSTABLE_SIZE * 2 * Controller.INVERSE_SQRT_2);
@@ -589,6 +647,6 @@ public void testMinSSTableSize()
589647
assertThatExceptionOfType(ConfigurationException.class)
590648
.describedAs("Should have thrown a ConfigurationException when min_sstable_size is greater than target_sstable_size")
591649
.isThrownBy(() -> Controller.validateOptions(options))
592-
.withMessageContaining(format("less than the target size minimum: %s", FBUtilities.prettyPrintMemory(limit)));
650+
.withMessageContaining(format("Invalid configuration, %s (%s) should be less than 70%% of the targetSSTableSize (%s)", Controller.MIN_SSTABLE_SIZE_OPTION, FBUtilities.prettyPrintMemory(limit + 1), FBUtilities.prettyPrintMemory(Controller.MIN_TARGET_SSTABLE_SIZE * 2)));
593651
}
594652
}

0 commit comments

Comments
 (0)