Skip to content

Commit

Permalink
Allow column_index_size_in_kb to be configurable through nodetool
Browse files Browse the repository at this point in the history
patch by Francisco Guerrero; reviewed by Dinesh Joshi, Yifan Cai for CASSANDRA-17121
  • Loading branch information
frankgh authored and yifan-c committed Dec 14, 2021
1 parent c64ff69 commit a41cdd6
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
@@ -1,4 +1,5 @@
4.1
* Allow column_index_size_in_kb to be configurable through nodetool (CASSANDRA-17121)
* Emit a metric for number of local read and write calls
* Add non-blocking mode for CDC writes (CASSANDRA-17001)
* Add guardrails framework (CASSANDRA-17147)
Expand Down
2 changes: 1 addition & 1 deletion src/java/org/apache/cassandra/config/Config.java
Expand Up @@ -223,7 +223,7 @@ public class Config
public volatile long snapshot_links_per_second = 0;

/* if the size of columns or super-columns are more than this, indexing will kick in */
public int column_index_size_in_kb = 64;
public volatile int column_index_size_in_kb = 64;
public volatile int column_index_cache_size_in_kb = 2;
public volatile int batch_size_warn_threshold_in_kb = 5;
public volatile int batch_size_fail_threshold_in_kb = 50;
Expand Down
Expand Up @@ -1513,7 +1513,6 @@ public static int getColumnIndexSizeInKB()
return conf.column_index_size_in_kb;
}

@VisibleForTesting
public static void setColumnIndexSize(int val)
{
checkValidForByteConversion(val, "column_index_size_in_kb", ByteUnit.KIBI_BYTES);
Expand Down
12 changes: 12 additions & 0 deletions src/java/org/apache/cassandra/service/StorageService.java
Expand Up @@ -5860,6 +5860,18 @@ public void setCachedReplicaRowsFailThreshold(int threshold)
logger.info("updated replica_filtering_protection.cached_rows_fail_threshold to {}", threshold);
}

public int getColumnIndexSizeInKB()
{
return DatabaseDescriptor.getColumnIndexSizeInKB();
}

public void setColumnIndexSize(int columnIndexSizeInKB)
{
int oldValueInKB = DatabaseDescriptor.getColumnIndexSizeInKB();
DatabaseDescriptor.setColumnIndexSize(columnIndexSizeInKB);
logger.info("Updated column_index_size_in_kb to {} KiB (was {} KiB)", columnIndexSizeInKB, oldValueInKB);
}

public int getColumnIndexCacheSize()
{
return DatabaseDescriptor.getColumnIndexCacheSizeInKB();
Expand Down
Expand Up @@ -767,6 +767,11 @@ default int upgradeSSTables(String keyspaceName, boolean excludeCurrentVersion,
/** Sets the number of rows cached at the coordinator before filtering/index queries fail outright. */
public void setCachedReplicaRowsFailThreshold(int threshold);

/** Returns the granularity of the collation index of rows within a partition **/
public int getColumnIndexSizeInKB();
/** Sets the granularity of the collation index of rows within a partition **/
public void setColumnIndexSize(int columnIndexSizeInKB);

/** Returns the threshold for skipping the column index when caching partition info **/
public int getColumnIndexCacheSize();
/** Sets the threshold for skipping the column index when caching partition info **/
Expand Down
10 changes: 10 additions & 0 deletions src/java/org/apache/cassandra/tools/NodeProbe.java
Expand Up @@ -1202,6 +1202,16 @@ public boolean isInitialized()
return ssProxy.isInitialized();
}

public void setColumnIndexSize(int columnIndexSizeInKB)
{
ssProxy.setColumnIndexSize(columnIndexSizeInKB);
}

public int getColumnIndexSizeInKB()
{
return ssProxy.getColumnIndexSizeInKB();
}

public void setCompactionThroughput(int value)
{
ssProxy.setCompactionThroughputMbPerSec(value);
Expand Down
2 changes: 2 additions & 0 deletions src/java/org/apache/cassandra/tools/NodeTool.java
Expand Up @@ -130,6 +130,7 @@ public int execute(String... args)
GcStats.class,
GetAuditLog.class,
GetBatchlogReplayTrottle.class,
GetColumnIndexSize.class,
GetCompactionThreshold.class,
GetCompactionThroughput.class,
GetConcurrency.class,
Expand Down Expand Up @@ -189,6 +190,7 @@ public int execute(String... args)
SetBatchlogReplayThrottle.class,
SetCacheCapacity.class,
SetCacheKeysToSave.class,
SetColumnIndexSize.class,
SetCompactionThreshold.class,
SetCompactionThroughput.class,
SetConcurrency.class,
Expand Down
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.cassandra.tools.nodetool;

import io.airlift.airline.Command;
import org.apache.cassandra.tools.NodeProbe;
import org.apache.cassandra.tools.NodeTool.NodeToolCmd;

@Command(name = "getcolumnindexsize", description = "Print the granularity of the collation index of rows within a partition in KiB")
public class GetColumnIndexSize extends NodeToolCmd
{
@Override
protected void execute(NodeProbe probe)
{
probe.output().out.println("Current value for column_index_size_in_kb: " + probe.getColumnIndexSizeInKB() + " KiB");
}
}
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.cassandra.tools.nodetool;

import io.airlift.airline.Arguments;
import io.airlift.airline.Command;
import org.apache.cassandra.tools.NodeProbe;
import org.apache.cassandra.tools.NodeTool.NodeToolCmd;

@Command(name = "setcolumnindexsize", description = "Set the granularity of the collation index of rows within a partition in KiB")
public class SetColumnIndexSize extends NodeToolCmd
{
@SuppressWarnings("UnusedDeclaration")
@Arguments(title = "column_index_size_in_kb", usage = "<value_in_kib>", description = "Value in KiB", required = true)
private int columnIndexSizeInKB;

@Override
protected void execute(NodeProbe probe)
{
probe.setColumnIndexSize(columnIndexSizeInKB);
}
}
@@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.cassandra.tools.nodetool;

import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.service.StorageService;

import static org.apache.cassandra.tools.ToolRunner.ToolResult;
import static org.apache.cassandra.tools.ToolRunner.invokeNodetool;
import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@code nodetool setcolumnindexsize} and {@code nodetool getcolumnindexsize}.
*/
public class SetGetColumnIndexSizeTest extends CQLTester
{
@BeforeClass
public static void setup() throws Exception
{
startJMXServer();
}

@Test
public void testNull()
{
assertSetInvalidColumnIndexSize(null, "Required parameters are missing: column_index_size_in_kb", 1);
}

@Test
public void testPositive()
{
assertSetGetValidColumnIndexSize(7);
}

@Test
public void testMaxValue()
{
assertSetGetValidColumnIndexSize(2097151);
}

@Test
public void testZero()
{
assertSetGetValidColumnIndexSize(0);
}

@Test
public void testNegative()
{
assertSetInvalidColumnIndexSize("-7", "column_index_size_in_kb must be positive value < 2097152, but was -7", 2);
}

@Test
public void testInvalidValue()
{
assertSetInvalidColumnIndexSize("2097152", "column_index_size_in_kb must be positive value < 2097152, but was 2097152", 2);
}

@Test
public void testUnparseable()
{
assertSetInvalidColumnIndexSize("1.2", "column_index_size_in_kb: can not convert \"1.2\" to a int", 1);
assertSetInvalidColumnIndexSize("value", "column_index_size_in_kb: can not convert \"value\" to a int", 1);
}

private static void assertSetGetValidColumnIndexSize(int columnIndexSizeInKB)
{
ToolResult tool = invokeNodetool("setcolumnindexsize", String.valueOf(columnIndexSizeInKB));
tool.assertOnCleanExit();
assertThat(tool.getStdout()).isEmpty();

assertGetThroughput(columnIndexSizeInKB);

assertThat(StorageService.instance.getColumnIndexSizeInKB()).isEqualTo(columnIndexSizeInKB);
}

private static void assertSetInvalidColumnIndexSize(String columnIndexSizeInKB, String expectedErrorMessage, int expectedErrorCode)
{
ToolResult tool = columnIndexSizeInKB == null ? invokeNodetool("setcolumnindexsize")
: invokeNodetool("setcolumnindexsize", columnIndexSizeInKB);
assertThat(tool.getExitCode()).isEqualTo(expectedErrorCode);
assertThat(expectedErrorCode == 1 ? tool.getStdout() : tool.getStderr()).contains(expectedErrorMessage);
}

private static void assertGetThroughput(int expected)
{
ToolResult tool = invokeNodetool("getcolumnindexsize");
tool.assertOnCleanExit();
assertThat(tool.getStdout()).contains("Current value for column_index_size_in_kb: " + expected + " KiB");
}
}

0 comments on commit a41cdd6

Please sign in to comment.