Harden the possible range of values for max dictionary size and max total sample size for dictionary training

patch by Stefan Miklosovic; reviewed by Yifan Cai for CASSANDRA-21194
This commit is contained in:
Stefan Miklosovic 2026-02-27 13:22:26 +01:00
parent 43a022c4fc
commit ce983cb89c
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
5 changed files with 52 additions and 4 deletions

View File

@ -1,4 +1,5 @@
5.1
* Harden the possible range of values for max dictionary size and max total sample size for dictionary training (CASSANDRA-21194)
* Implement a guardrail ensuring that minimum training frequency parameter is provided in ZstdDictionaryCompressor (CASSANDRA-21192)
* Replace manual referencing with ColumnFamilyStore.selectAndReference when training a dictionary (CASSANDRA-21188)
* Forbid nodes upgrading to a version which cannot read existing log entries (CASSANDRA-21174)

View File

@ -471,7 +471,7 @@ public class CompressionDictionaryManager implements CompressionDictionaryManage
else
resolvedValue = userSuppliedValue;
return new DataStorageSpec.IntKibibytesBound(resolvedValue).toBytes();
return new DataStorageSpec.IntBytesBound(resolvedValue).toBytes();
}
catch (Throwable t)
{

View File

@ -59,7 +59,7 @@ public interface IDictionaryCompressor<T extends CompressionDictionary>
{
try
{
new DataStorageSpec.IntKibibytesBound(resolvedValue).toBytes();
new DataStorageSpec.IntBytesBound(resolvedValue).toBytes();
}
catch (Throwable t)
{

View File

@ -182,7 +182,7 @@ public class CompressionDictionaryCommandGroup
{
try
{
new DataStorageSpec.IntKibibytesBound(trainingMaxDictionarySize).toBytes();
new DataStorageSpec.IntBytesBound(trainingMaxDictionarySize).toBytes();
}
catch (Throwable t)
{
@ -195,7 +195,7 @@ public class CompressionDictionaryCommandGroup
{
try
{
new DataStorageSpec.IntKibibytesBound(trainingMaxTotalSampleSize).toBytes();
new DataStorageSpec.IntBytesBound(trainingMaxTotalSampleSize).toBytes();
}
catch (Throwable t)
{

View File

@ -234,6 +234,33 @@ public class CompressionDictionaryIntegrationTest extends CQLTester
.hasMessageContaining("No SSTables available for training");
}
@Test
public void testMaxBoundForTrainingParameters()
{
String table = createTable(getTableCql());
ColumnFamilyStore cfs = Keyspace.open(keyspace()).getColumnFamilyStore(table);
CompressionDictionaryManager manager = cfs.compressionDictionaryManager();
assertThatThrownBy(() -> manager.train(false, Map.of(TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_NAME, "5GiB",
TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME, TRAINING_MAX_TOTAL_SAMPLE_SIZE)))
.as("Should fail when " + TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_NAME + " is bigger than " + Integer.MAX_VALUE)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Invalid value for training_max_dictionary_size: 5GiB");
assertThatThrownBy(() -> manager.train(false, Map.of(TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_NAME, TRAINING_MAX_DICTIONARY_SIZE,
TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME, "5GiB")))
.as("Should fail when " + TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME + " is bigger than " + Integer.MAX_VALUE)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Invalid value for " + TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME + ": 5GiB");
}
@Test
public void testInvalidTableCreation()
{
assertThatThrownBy(() -> createTable(getTableCqlWithInvalidTotalMaxSampleSize())).isInstanceOf(RuntimeException.class);
assertThatThrownBy(() -> createTable(getTableCqlWithInvalidMaxDictionarySize())).isInstanceOf(RuntimeException.class);
}
private String getTableCqlWithChunkLength()
{
return "CREATE TABLE %s (pk text PRIMARY KEY, data text) " +
@ -254,4 +281,24 @@ public class CompressionDictionaryIntegrationTest extends CQLTester
'\'' + TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME + "': '" + DEFAULT_TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_VALUE + '\'' +
'}';
}
private String getTableCqlWithInvalidTotalMaxSampleSize()
{
return "CREATE TABLE %s (pk text PRIMARY KEY, data text) " +
"WITH compression = {" +
"'class': 'ZstdDictionaryCompressor'," +
'\'' + TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_NAME + "': '" + DEFAULT_TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_VALUE + "'," +
'\'' + TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME + "': '5GiB'" +
'}';
}
private String getTableCqlWithInvalidMaxDictionarySize()
{
return "CREATE TABLE %s (pk text PRIMARY KEY, data text) " +
"WITH compression = {" +
"'class': 'ZstdDictionaryCompressor'," +
'\'' + TRAINING_MAX_DICTIONARY_SIZE_PARAMETER_NAME + "': '5GiB'," +
'\'' + TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_NAME + "': '" + DEFAULT_TRAINING_MAX_TOTAL_SAMPLE_SIZE_PARAMETER_VALUE + '\'' +
'}';
}
}