Skip to content

Commit 35d6f8c

Browse files
Guardrail values of zero to mean literally zero
Before guardrail values of -1 and 0 both mean unlimited. Now zero means zero, for example "more than 0 is a warning" or "more than 0 is a failure". patch by Mick Semb Wever; reviewed by David Capwell, Jeremiah Jordan for CASSANDRA-21517
1 parent 38a7a78 commit 35d6f8c

12 files changed

Lines changed: 296 additions & 78 deletions

File tree

‎CHANGES.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
6.0-alpha3
2+
* Guardrail configurations of zero are now treated as zero instead of unlimited (CASSANDRA-21517)
23
* Support multi-cell columns in cursor compaction (CASSANDRA-21463)
34
* Optimize authorization logic for BatchStatement and TransactionStatement when a single table is updated (CASSANDRA-21606)
45
* Upgrade lz4-java to 1.11.2 (CASSANDRA-21564)

‎NEWS.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ Upgrading
209209
unchanged, and the datacenter and CIDR checks that ride along with them still run at least once per
210210
request. Auth cache request/hit/miss counts and the system_views.cidr_filtering_metrics_* counts and
211211
latencies will therefore report fewer events than before. (see CASSANDRA-21606)
212+
- Guardrail configurations of zero are now treated as zero instead of unlimited. See CASSANDRA-21517.
212213

213214
Deprecation
214215
-----------

‎src/java/org/apache/cassandra/config/GuardrailsOptions.java‎

Lines changed: 42 additions & 58 deletions
Large diffs are not rendered by default.

‎src/java/org/apache/cassandra/db/guardrails/MaxThreshold.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ protected boolean compare(long value, long threshold)
5757
public long failValue(ClientState state)
5858
{
5959
long failValue = failThreshold.applyAsLong(state);
60-
return failValue <= 0 ? Long.MAX_VALUE : failValue;
60+
return failValue < 0 ? Long.MAX_VALUE : failValue;
6161
}
6262

6363
@Override
6464
public long warnValue(ClientState state)
6565
{
6666
long warnValue = warnThreshold.applyAsLong(state);
67-
return warnValue <= 0 ? Long.MAX_VALUE : warnValue;
67+
return warnValue < 0 ? Long.MAX_VALUE : warnValue;
6868
}
6969

7070
}

‎src/java/org/apache/cassandra/db/guardrails/MinThreshold.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ protected boolean compare(long value, long threshold)
5757
protected long failValue(ClientState state)
5858
{
5959
long failValue = failThreshold.applyAsLong(state);
60-
return failValue <= 0 ? Long.MIN_VALUE : failValue;
60+
return failValue < 0 ? Long.MIN_VALUE : failValue;
6161
}
6262

6363
@Override
6464
protected long warnValue(ClientState state)
6565
{
6666
long warnValue = warnThreshold.applyAsLong(state);
67-
return warnValue <= 0 ? Long.MIN_VALUE : warnValue;
67+
return warnValue < 0 ? Long.MIN_VALUE : warnValue;
6868
}
6969

7070
}

‎src/java/org/apache/cassandra/db/guardrails/Threshold.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ public boolean enabled(@Nullable ClientState state)
8383
if (!super.enabled(state))
8484
return false;
8585

86-
return failThreshold.applyAsLong(state) > 0 || warnThreshold.applyAsLong(state) > 0;
86+
// A negative threshold is the disabled marker. Zero is a real threshold, meaning "any value above zero
87+
// triggers", so a guardrail with either threshold set to zero is enabled.
88+
return failThreshold.applyAsLong(state) >= 0 || warnThreshold.applyAsLong(state) >= 0;
8789
}
8890

8991
/**
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.cassandra.config;
20+
21+
import org.assertj.core.api.Assertions;
22+
import org.junit.BeforeClass;
23+
import org.junit.Test;
24+
25+
import static org.junit.Assert.assertEquals;
26+
import static org.junit.Assert.assertNull;
27+
28+
/**
29+
* Tests the guardrail thresholds a {@code cassandra.yaml} can carry, which {@link GuardrailsOptions} validates on
30+
* construction. See CASSANDRA-21517 for the treatment of zero.
31+
*/
32+
public class GuardrailsOptionsTest
33+
{
34+
@BeforeClass
35+
public static void setupDatabaseDescriptor()
36+
{
37+
DatabaseDescriptor.daemonInitialization();
38+
}
39+
40+
@Test
41+
public void testZeroThresholdsAreAccepted()
42+
{
43+
Config config = new Config();
44+
config.tables_fail_threshold = 0;
45+
config.keyspaces_warn_threshold = 0;
46+
config.partition_tombstones_fail_threshold = 0;
47+
config.data_disk_usage_percentage_warn_threshold = 0;
48+
config.partition_size_fail_threshold = new DataStorageSpec.LongBytesBound("0B");
49+
config.column_value_size_warn_threshold = new DataStorageSpec.LongBytesBound("0B");
50+
51+
GuardrailsOptions options = new GuardrailsOptions(config);
52+
53+
assertEquals(0, options.getTablesFailThreshold());
54+
assertEquals(0, options.getKeyspacesWarnThreshold());
55+
assertEquals(0, options.getPartitionTombstonesFailThreshold());
56+
assertEquals(0, options.getDataDiskUsagePercentageWarnThreshold());
57+
assertEquals(0, options.getPartitionSizeFailThreshold().toBytes());
58+
assertEquals(0, options.getColumnValueSizeWarnThreshold().toBytes());
59+
}
60+
61+
@Test
62+
public void testMinusOneAndNullDisableThresholds()
63+
{
64+
Config config = new Config();
65+
config.tables_fail_threshold = -1;
66+
config.partition_size_fail_threshold = null;
67+
68+
GuardrailsOptions options = new GuardrailsOptions(config);
69+
70+
assertEquals(-1, options.getTablesFailThreshold());
71+
assertNull(options.getPartitionSizeFailThreshold());
72+
}
73+
74+
@Test
75+
public void testValuesBelowMinusOneAreRejected()
76+
{
77+
Config config = new Config();
78+
config.tables_fail_threshold = -2;
79+
80+
Assertions.assertThatThrownBy(() -> new GuardrailsOptions(config))
81+
.isInstanceOf(IllegalArgumentException.class)
82+
.hasMessageContaining("negative values are not allowed, outside of -1 which disables the guardrail");
83+
}
84+
}

‎test/unit/org/apache/cassandra/db/guardrails/GuardrailDiskUsageTest.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ public void testConfigValidation()
126126
// We want to test with very big number, Long.MAX_VALUE is not allowed so it was easy to use Intger.MAX_VALUE
127127
assertConfigFails(x -> x.setDataDiskUsageMaxDiskSize(Integer.MAX_VALUE + "GiB"), message);
128128

129-
// warn threshold smaller than lower bound
130-
assertConfigFails(x -> x.setDataDiskUsagePercentageThreshold(0, 80), "0 is not allowed");
129+
// a warn threshold of zero warns on any disk usage above zero, it does not disable the guardrail
130+
assertConfigValid(x -> x.setDataDiskUsagePercentageThreshold(0, 80));
131+
assertEquals(0, guardrails().getDataDiskUsagePercentageWarnThreshold());
131132

132133
// fail threshold bigger than upper bound
133134
assertConfigFails(x -> x.setDataDiskUsagePercentageThreshold(1, 110), "maximum allowed value is 100");

‎test/unit/org/apache/cassandra/db/guardrails/GuardrailMaximumReplicationFactorTest.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ public GuardrailMaximumReplicationFactorTest()
5151
Guardrails::getMaximumReplicationFactorFailThreshold);
5252
}
5353

54+
@Override
55+
protected boolean zeroIsValid()
56+
{
57+
// a maximum replication factor of zero would be lower than default_keyspace_rf, which is rejected
58+
// by validateMaxRFThreshold rather than by the threshold validation itself
59+
return false;
60+
}
61+
5462
@After
5563
public void cleanupTest() throws Throwable
5664
{

‎test/unit/org/apache/cassandra/db/guardrails/GuardrailMinimumReplicationFactorTest.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ public void testConfigValidation()
106106
assertInvalidPositiveIntProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), Integer.MIN_VALUE, Integer.MAX_VALUE, WHAT + "_fail_threshold");
107107
assertInvalidPositiveIntProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), -2, Integer.MAX_VALUE, WHAT + "_fail_threshold");
108108
assertValidProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), DISABLED_GUARDRAIL);
109-
assertInvalidPositiveIntProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), 0, Integer.MAX_VALUE, WHAT + "_fail_threshold");
109+
assertValidProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), 0);
110110
assertValidProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), 1);
111111
assertValidProperty((g, a) -> setter.accept(g, DISABLED_GUARDRAIL, a), 2);
112112

113113
assertInvalidPositiveIntProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), Integer.MIN_VALUE, Integer.MAX_VALUE, WHAT + "_warn_threshold");
114114
assertInvalidPositiveIntProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), -2, Integer.MAX_VALUE, WHAT + "_warn_threshold");
115115
assertValidProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), DISABLED_GUARDRAIL);
116-
assertInvalidPositiveIntProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), 0, Integer.MAX_VALUE, WHAT + "_warn_threshold");
116+
assertValidProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), 0);
117117
assertValidProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), 1);
118118
assertValidProperty((g, w) -> setter.accept(g, w, DISABLED_GUARDRAIL), 2);
119119

0 commit comments

Comments
 (0)