Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .build/cassandra-deps-template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@
<groupId>io.airlift</groupId>
<artifactId>airline</artifactId>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
</dependency>
<dependency>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
Expand Down
10 changes: 10 additions & 0 deletions .build/parent-pom-template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,16 @@
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.7.5</version>
</dependency>
<dependency>
<groupId>io.github.java-diff-utils</groupId>
<artifactId>java-diff-utils</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>io.airlift</groupId>
<artifactId>airline</artifactId>
Expand Down
10 changes: 8 additions & 2 deletions bin/nodetool
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,19 @@ if [ "x$MAX_HEAP_SIZE" = "x" ]; then
MAX_HEAP_SIZE="128m"
fi

if [ "x$NODETOOL_RUNNER" = "x" ]; then
NODETOOL_RUNNER="org.apache.cassandra.tools.NodeTool"
fi

# shellcheck disable=SC2116
CMD=$(echo "$JAVA" $JAVA_AGENT -ea -cp "$CLASSPATH" $JVM_OPTS -Xmx$MAX_HEAP_SIZE \
-XX:ParallelGCThreads=1 \
-Dcassandra.storagedir="$cassandra_storagedir" \
-Dcassandra.logdir="$CASSANDRA_LOG_DIR" \
-Dlogback.configurationFile=logback-tools.xml \
$JVM_ARGS \
org.apache.cassandra.tools.NodeTool -p $JMX_PORT $ARGS)
"$JVM_ARGS" \
$NODETOOL_RUNNER \
-p "$JMX_PORT" "$ARGS")

if [ "x$ARCHIVE_COMMAND" != "x" ]
then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public enum CassandraRelevantProperties
CACHEABLE_MUTATION_SIZE_LIMIT("cassandra.cacheable_mutation_size_limit_bytes", convertToString(1_000_000)),
CASSANDRA_ALLOW_SIMPLE_STRATEGY("cassandra.allow_simplestrategy"),
CASSANDRA_AVAILABLE_PROCESSORS("cassandra.available_processors"),
CASSANDRA_CLI_PICOCLI_LAYOUT("cassandra.cli.picocli.layout", "false"),
/** The classpath storage configuration file. */
CASSANDRA_CONFIG("cassandra.config", "cassandra.yaml"),
/**
Expand Down
51 changes: 51 additions & 0 deletions src/java/org/apache/cassandra/management/BaseCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.management;

import picocli.CommandLine;

/**
* Base class for all nodetool commands.
*/
public abstract class BaseCommand implements Runnable
{
/** The command specification, used to access command-specific properties. */
@CommandLine.Spec
protected CommandLine.Model.CommandSpec spec; // injected by picocli
/** The ServiceBridge instance to interact with the Cassandra node. */
protected ServiceBridge bridge;

/**
* The ServiceBridge instance is injected by the picocli framework during command execution and is used to
* interact with the Cassandra node. This method is called by picocli and used depending on the execution strategy.
* @param bridge The ServiceBridge instance to inject.
*/
public void setBridge(ServiceBridge bridge)
{
this.bridge = bridge;
}

@Override
public void run()
{
execute(bridge);
}

protected abstract void execute(ServiceBridge probe);
}
120 changes: 120 additions & 0 deletions src/java/org/apache/cassandra/management/CassandraHelpCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* 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.management;

import java.io.PrintWriter;
import java.util.Map;

import com.google.common.base.Preconditions;

import picocli.CommandLine;

@CommandLine.Command(name = "help",
header = "Display help information about the specified command.",
synopsisHeading = "%nUsage: ",
helpCommand = true,
description = { "%nWhen no COMMAND is given, the usage help for the main command is displayed.",
"If a COMMAND is specified, the help for that command is shown.%n" })
public class CassandraHelpCommand implements CommandLine.IHelpCommandInitializable2, Runnable
{
@CommandLine.Option(names = { "--help" }, usageHelp = true, descriptionKey = "helpCommand.help",
description = "Show usage help for the help command and exit.")
private boolean helpRequested;

@CommandLine.Parameters(paramLabel = "command", arity = "0..1", descriptionKey = "helpCommand.command",
description = "The COMMAND to display the usage help message for.")
private String commands;

private CommandLine self;
private PrintWriter out;
private CommandLine.Help.ColorScheme colorScheme;

/**
* Invokes {@code #usage(PrintStream, CommandLine.Help.ColorScheme) usage} for the specified command,
* or for the parent command.
*/
public void run()
{
CommandLine parent = self == null ? null : self.getParent();
if (parent == null)
return;

CommandLine.Help.ColorScheme colors = colorScheme == null ?
CommandLine.Help.defaultColorScheme(CommandLine.Help.Ansi.AUTO) :
colorScheme;

if (commands == null)
{
// If the parent command is the top-level command, print help for the top-level command.
printTopCommandUsage(parent, colors, out);
return;
}

Map<String, CommandLine> parentSubcommands = parent.getCommandSpec().subcommands();
CommandLine subcommand = parentSubcommands.get(commands);

if (parent.isAbbreviatedSubcommandsAllowed())
throw new CommandLine.ParameterException(parent, "Abbreviated subcommands are not allowed.", null, commands);

if (subcommand == null)
throw new CommandLine.ParameterException(parent, "Unknown subcommand '" + commands + "'.", null, commands);

subcommand.usage(out, colors);
}

public static void printTopCommandUsage(CommandLine command, CommandLine.Help.ColorScheme colors, PrintWriter writer)
{
if (command == null)
return;

StringBuilder sb = new StringBuilder();
CommandLine.Help help = command.getHelpFactory().create(command.getCommandSpec(), colors);
if (!(help instanceof CassandraHelpLayout))
{
command.usage(writer, colors);
return;
}

Map<String, CommandLine.IHelpSectionRenderer> helpSectionMap = CassandraHelpLayout.cassandraTopLevelHelpSectionKeys((CassandraHelpLayout) help);
for (String key : command.getHelpSectionKeys())
{
CommandLine.IHelpSectionRenderer renderer = helpSectionMap.get(key);
if (renderer == null)
continue;
sb.append(renderer.render(help));
}

writer.println(sb);
writer.flush();
}

/**
* The printHelpIfRequested method calls the init method on commands marked
* as helpCommand before the help command's run or call method is called.
*/
public void init(CommandLine helpCommandLine,
CommandLine.Help.ColorScheme colorScheme,
PrintWriter out,
PrintWriter err)
{
this.self = Preconditions.checkNotNull(helpCommandLine, "helpCommandLine");
this.colorScheme = Preconditions.checkNotNull(colorScheme, "colorScheme");
this.out = Preconditions.checkNotNull(out, "outWriter");
}
}
Loading