This is an automated email from the ASF dual-hosted git repository.
technoboy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 69c45ad5300 [improve][cli] PIP-343: Use picocli instead of jcommander
in pulsar-perf (#22303)
69c45ad5300 is described below
commit 69c45ad5300e36a62a923b8eaa58aab99c6e02fb
Author: crossoverJie <[email protected]>
AuthorDate: Fri Mar 22 09:12:37 2024 +0800
[improve][cli] PIP-343: Use picocli instead of jcommander in pulsar-perf
(#22303)
Co-authored-by: Zixuan Liu <[email protected]>
---
.../cli/converters/ByteUnitToLongConverter.java | 39 ---------
.../pulsar/cli/converters/ByteConversionTest.java | 9 +-
pulsar-testclient/pom.xml | 4 +-
.../proxy/socket/client/PerformanceClient.java | 65 +++++++--------
.../apache/pulsar/testclient/BrokerMonitor.java | 30 +++----
.../testclient/CmdGenerateDocumentation.java | 67 +++++++++------
.../pulsar/testclient/LoadSimulationClient.java | 34 ++++----
.../testclient/LoadSimulationController.java | 68 +++++++--------
.../pulsar/testclient/ManagedLedgerWriter.java | 57 ++++++-------
.../testclient/PerformanceBaseArguments.java | 59 +++++++------
.../pulsar/testclient/PerformanceConsumer.java | 65 ++++++++-------
.../pulsar/testclient/PerformanceProducer.java | 96 +++++++++++-----------
.../pulsar/testclient/PerformanceReader.java | 19 +++--
.../testclient/PerformanceTopicListArguments.java | 10 ++-
.../pulsar/testclient/PerformanceTransaction.java | 45 +++++-----
...or.java => PositiveNumberParameterConvert.java} | 15 ++--
.../pulsar/testclient/GenerateDocumentionTest.java | 37 +++++++++
17 files changed, 377 insertions(+), 342 deletions(-)
diff --git
a/pulsar-cli-utils/src/main/java/org/apache/pulsar/cli/converters/ByteUnitToLongConverter.java
b/pulsar-cli-utils/src/main/java/org/apache/pulsar/cli/converters/ByteUnitToLongConverter.java
deleted file mode 100644
index 6170fb489d4..00000000000
---
a/pulsar-cli-utils/src/main/java/org/apache/pulsar/cli/converters/ByteUnitToLongConverter.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.pulsar.cli.converters;
-
-import static org.apache.pulsar.cli.ValueValidationUtil.emptyCheck;
-import com.beust.jcommander.converters.BaseConverter;
-
-public class ByteUnitToLongConverter extends BaseConverter<Long> {
-
- public ByteUnitToLongConverter(String optionName) {
- super(optionName);
- }
-
- @Override
- public Long convert(String argStr) {
- return parseBytes(argStr);
- }
-
- Long parseBytes(String argStr) {
- emptyCheck(getOptionName(), argStr);
- return ByteUnitUtil.validateSizeString(argStr);
- }
-}
diff --git
a/pulsar-cli-utils/src/test/java/org/apache/pulsar/cli/converters/ByteConversionTest.java
b/pulsar-cli-utils/src/test/java/org/apache/pulsar/cli/converters/ByteConversionTest.java
index 283e94bfb9c..6e7a2e6d7e3 100644
---
a/pulsar-cli-utils/src/test/java/org/apache/pulsar/cli/converters/ByteConversionTest.java
+++
b/pulsar-cli-utils/src/test/java/org/apache/pulsar/cli/converters/ByteConversionTest.java
@@ -21,6 +21,7 @@ package org.apache.pulsar.cli.converters;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertThrows;
import org.apache.pulsar.cli.converters.picocli.ByteUnitToIntegerConverter;
+import org.apache.pulsar.cli.converters.picocli.ByteUnitToLongConverter;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import picocli.CommandLine.TypeConversionException;
@@ -59,8 +60,8 @@ public class ByteConversionTest {
}
@Test(dataProvider = "successfulByteUnitUtilTestCases")
- public void testSuccessfulByteUnitToLongConverter(String input, long
expected) {
- ByteUnitToLongConverter converter = new
ByteUnitToLongConverter("optionName");
+ public void testSuccessfulByteUnitToLongConverter(String input, long
expected) throws Exception{
+ ByteUnitToLongConverter converter = new ByteUnitToLongConverter();
assertEquals(converter.convert(input), Long.valueOf(expected));
}
@@ -78,8 +79,8 @@ public class ByteConversionTest {
@Test(dataProvider = "failingByteUnitUtilTestCases")
public void testFailedByteUnitToLongConverter(String input) {
- ByteUnitToLongConverter converter = new
ByteUnitToLongConverter("optionName");
- assertThrows(IllegalArgumentException.class, () ->
converter.convert(input));
+ ByteUnitToLongConverter converter = new ByteUnitToLongConverter();
+ assertThrows(TypeConversionException.class, () ->
converter.convert(input));
}
@Test(dataProvider = "failingByteUnitUtilTestCases")
diff --git a/pulsar-testclient/pom.xml b/pulsar-testclient/pom.xml
index db2b84356e6..ecc12b2e563 100644
--- a/pulsar-testclient/pom.xml
+++ b/pulsar-testclient/pom.xml
@@ -97,8 +97,8 @@
</dependency>
<dependency>
- <groupId>com.beust</groupId>
- <artifactId>jcommander</artifactId>
+ <groupId>info.picocli</groupId>
+ <artifactId>picocli</artifactId>
<scope>compile</scope>
</dependency>
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java
index 596eb8d2c28..9d95d0b74a2 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java
@@ -20,10 +20,6 @@ package org.apache.pulsar.proxy.socket.client;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import com.google.common.util.concurrent.RateLimiter;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.FileInputStream;
@@ -55,13 +51,18 @@ import org.apache.pulsar.client.api.AuthenticationFactory;
import org.apache.pulsar.common.naming.TopicName;
import org.apache.pulsar.testclient.IMessageFormatter;
import org.apache.pulsar.testclient.PerfClientUtils;
-import org.apache.pulsar.testclient.PositiveNumberParameterValidator;
+import org.apache.pulsar.testclient.PositiveNumberParameterConvert;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.Parameters;
public class PerformanceClient {
@@ -70,87 +71,87 @@ public class PerformanceClient {
private static final LongAdder totalMessagesSent = new LongAdder();
private static final LongAdder totalBytesSent = new LongAdder();
private static IMessageFormatter messageFormatter = null;
- private JCommander jc;
+ private CommandLine commander;
- @Parameters(commandDescription = "Test pulsar websocket producer
performance.")
+ @Command(description = "Test pulsar websocket producer performance.")
static class Arguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Help message", help
= true)
boolean help;
- @Parameter(names = { "-cf", "--conf-file" }, description =
"Configuration file")
+ @Option(names = { "-cf", "--conf-file" }, description = "Configuration
file")
public String confFile;
- @Parameter(names = { "-u", "--proxy-url" }, description = "Pulsar
Proxy URL, e.g., \"ws://localhost:8080/\"")
+ @Option(names = { "-u", "--proxy-url" }, description = "Pulsar Proxy
URL, e.g., \"ws://localhost:8080/\"")
public String proxyURL;
- @Parameter(description = "persistent://tenant/ns/my-topic", required =
true)
+ @Parameters(description = "persistent://tenant/ns/my-topic", arity =
"1")
public List<String> topics;
- @Parameter(names = { "-r", "--rate" }, description = "Publish rate
msg/s across topics")
+ @Option(names = { "-r", "--rate" }, description = "Publish rate msg/s
across topics")
public int msgRate = 100;
- @Parameter(names = { "-s", "--size" }, description = "Message size in
byte")
+ @Option(names = { "-s", "--size" }, description = "Message size in
byte")
public int msgSize = 1024;
- @Parameter(names = { "-t", "--num-topic" }, description = "Number of
topics",
- validateWith = PositiveNumberParameterValidator.class)
+ @Option(names = { "-t", "--num-topic" }, description = "Number of
topics",
+ converter = PositiveNumberParameterConvert.class
+ )
public int numTopics = 1;
- @Parameter(names = { "--auth_plugin" }, description = "Authentication
plugin class name", hidden = true)
+ @Option(names = { "--auth_plugin" }, description = "Authentication
plugin class name", hidden = true)
public String deprecatedAuthPluginClassName;
- @Parameter(names = { "--auth-plugin" }, description = "Authentication
plugin class name")
+ @Option(names = { "--auth-plugin" }, description = "Authentication
plugin class name")
public String authPluginClassName;
- @Parameter(
+ @Option(
names = { "--auth-params" },
description = "Authentication parameters, whose format is
determined by the implementation "
+ "of method `configure` in authentication plugin class,
for example \"key1:val1,key2:val2\" "
+ "or \"{\"key1\":\"val1\",\"key2\":\"val2\"}\".")
public String authParams;
- @Parameter(names = { "-m",
+ @Option(names = { "-m",
"--num-messages" }, description = "Number of messages to
publish in total. If <= 0, it will keep"
+ " publishing")
public long numMessages = 0;
- @Parameter(names = { "-f", "--payload-file" }, description = "Use
payload from a file instead of empty buffer")
+ @Option(names = { "-f", "--payload-file" }, description = "Use payload
from a file instead of empty buffer")
public String payloadFilename = null;
- @Parameter(names = { "-e", "--payload-delimiter" },
+ @Option(names = { "-e", "--payload-delimiter" },
description = "The delimiter used to split lines when using
payload from a file")
// here escaping \n since default value will be printed with the help
text
public String payloadDelimiter = "\\n";
- @Parameter(names = { "-fp", "--format-payload" },
+ @Option(names = { "-fp", "--format-payload" },
description = "Format %i as a message index in the stream from
producer and/or %t as the timestamp"
+ " nanoseconds")
public boolean formatPayload = false;
- @Parameter(names = {"-fc", "--format-class"}, description = "Custom
Formatter class name")
+ @Option(names = {"-fc", "--format-class"}, description = "Custom
Formatter class name")
public String formatterClass =
"org.apache.pulsar.testclient.DefaultMessageFormatter";
- @Parameter(names = { "-time",
+ @Option(names = { "-time",
"--test-duration" }, description = "Test duration in secs. If
<= 0, it will keep publishing")
public long testTime = 0;
}
public Arguments loadArguments(String[] args) {
Arguments arguments = new Arguments();
- jc = new JCommander(arguments);
- jc.setProgramName("pulsar-perf websocket-producer");
-
+ commander = new CommandLine(arguments);
+ commander.setCommandName("pulsar-perf websocket-producer");
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
if (arguments.help) {
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
@@ -160,7 +161,7 @@ public class PerformanceClient {
if (arguments.topics.size() != 1) {
System.err.println("Only one topic name is allowed");
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
@@ -171,7 +172,7 @@ public class PerformanceClient {
prop.load(new FileInputStream(arguments.confFile));
} catch (IOException e) {
log.error("Error in loading config file");
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/BrokerMonitor.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/BrokerMonitor.java
index a3e5a14a416..d195e8fd456 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/BrokerMonitor.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/BrokerMonitor.java
@@ -20,10 +20,6 @@ package org.apache.pulsar.testclient;
import static
org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl.BROKER_LOAD_DATA_STORE_TOPIC;
import static
org.apache.pulsar.broker.resources.LoadBalanceResources.BROKER_TIME_AVERAGE_BASE_PATH;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Arrays;
@@ -50,6 +46,11 @@ import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.ScopeType;
/**
* Monitors brokers and prints to the console information about their system
resource usages, their topic and bundle
@@ -434,17 +435,18 @@ public class BrokerMonitor {
}
}
- // JCommander arguments class.
- @Parameters(commandDescription = "Monitors brokers and prints to the
console information about their system "
- + "resource usages, \ntheir topic and bundle counts, their message
rates, and other metrics.")
+ // picocli arguments class.
+ @Command(description = "Monitors brokers and prints to the console
information about their system "
+ + "resource usages, \ntheir topic and bundle counts, their message
rates, and other metrics.",
+ showDefaultValues = true, scope = ScopeType.INHERIT)
private static class Arguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Help message", help
= true)
boolean help;
- @Parameter(names = { "--connect-string" }, description = "Zookeeper or
broker connect string", required = true)
+ @Option(names = { "--connect-string" }, description = "Zookeeper or
broker connect string", required = true)
public String connectString = null;
- @Parameter(names = { "--extensions" }, description = "true to monitor
Load Balance Extensions.")
+ @Option(names = { "--extensions" }, description = "true to monitor
Load Balance Extensions.")
boolean extensions = false;
}
@@ -546,14 +548,14 @@ public class BrokerMonitor {
*/
public static void main(String[] args) throws Exception {
final Arguments arguments = new Arguments();
- final JCommander jc = new JCommander(arguments);
- jc.setProgramName("pulsar-perf monitor-brokers");
+ final CommandLine commander = new CommandLine(arguments);
+ commander.setCommandName("pulsar-perf monitor-brokers");
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/CmdGenerateDocumentation.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/CmdGenerateDocumentation.java
index e3aca988655..6ff0ab296a6 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/CmdGenerateDocumentation.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/CmdGenerateDocumentation.java
@@ -18,46 +18,47 @@
*/
package org.apache.pulsar.testclient;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterDescription;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.ScopeType;
@Slf4j
public class CmdGenerateDocumentation {
- @Parameters(commandDescription = "Generate documentation automatically.")
+ @Command(description = "Generate documentation automatically.",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments {
- @Parameter(names = {"-h", "--help"}, description = "Help message",
help = true)
+ @Option(names = {"-h", "--help"}, description = "Help message", help =
true)
boolean help;
- @Parameter(names = {"-n", "--command-names"}, description = "List of
command names")
+ @Option(names = {"-n", "--command-names"}, description = "List of
command names")
private List<String> commandNames = new ArrayList<>();
}
public static void main(String[] args) throws Exception {
final Arguments arguments = new Arguments();
- final JCommander jc = new JCommander(arguments);
- jc.setProgramName("pulsar-perf gen-doc");
+ CommandLine commander = new CommandLine(arguments);
+ commander.setCommandName("pulsar-perf gen-doc");
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
+
if (arguments.help) {
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
@@ -80,38 +81,54 @@ public class CmdGenerateDocumentation {
Class<?> clazz = entry.getValue();
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
- jc.addCommand(cmd, constructor.newInstance());
+ commander.addSubcommand(cmd, constructor.newInstance());
}
if (arguments.commandNames.size() == 0) {
- for (Map.Entry<String, JCommander> cmd :
jc.getCommands().entrySet()) {
- generateDocument(cmd.getKey(), jc);
+ for (Map.Entry<String, CommandLine> cmd :
commander.getSubcommands().entrySet()) {
+ generateDocument(cmd.getKey(), commander);
}
} else {
for (String commandName : arguments.commandNames) {
- generateDocument(commandName, jc);
+ generateDocument(commandName, commander);
}
}
}
- private static String generateDocument(String module, JCommander
parentCmd) {
+ private static String generateDocument(String module, CommandLine
parentCmd) {
StringBuilder sb = new StringBuilder();
- JCommander cmd = parentCmd.getCommands().get(module);
+ CommandLine cmd = parentCmd.getSubcommands().get(module);
sb.append("## ").append(module).append("\n\n");
-
sb.append(parentCmd.getUsageFormatter().getCommandDescription(module)).append("\n");
+ sb.append(getCommandDescription(cmd)).append("\n");
sb.append("\n\n```shell\n")
.append("$ pulsar-perf ").append(module).append(" [options]")
.append("\n```");
sb.append("\n\n");
sb.append("|Flag|Description|Default|\n");
sb.append("|---|---|---|\n");
- List<ParameterDescription> options = cmd.getParameters();
- options.stream().filter(ele ->
!ele.getParameterAnnotation().hidden()).forEach((option) ->
- sb.append("| `").append(option.getNames())
- .append("` |
").append(option.getDescription().replace("\n", " "))
- .append("|").append(option.getDefault()).append("|\n")
+ List<CommandLine.Model.OptionSpec> options =
cmd.getCommandSpec().options();
+ options.stream().filter(ele -> !ele.hidden()).forEach((option) ->
+ sb.append("| `").append(String.join(", ", option.names()))
+ .append("` |
").append(getOptionDescription(option).replace("\n", " "))
+
.append("|").append(option.defaultValueString()).append("|\n")
);
System.out.println(sb.toString());
return sb.toString();
}
+
+ public static String getCommandDescription(CommandLine commandLine) {
+ String[] description =
commandLine.getCommandSpec().usageMessage().description();
+ if (description != null && description.length != 0) {
+ return description[0];
+ }
+ return "";
+ }
+
+ public static String getOptionDescription(CommandLine.Model.OptionSpec
optionSpec) {
+ String[] description = optionSpec.description();
+ if (description != null && description.length != 0) {
+ return description[0];
+ }
+ return "";
+ }
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationClient.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationClient.java
index 982c71ce6a5..42d2f0dd514 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationClient.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationClient.java
@@ -18,10 +18,6 @@
*/
package org.apache.pulsar.testclient;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import com.google.common.util.concurrent.RateLimiter;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.DataInputStream;
@@ -37,7 +33,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
-import org.apache.pulsar.cli.converters.ByteUnitToLongConverter;
+import org.apache.pulsar.cli.converters.picocli.ByteUnitToLongConverter;
import org.apache.pulsar.client.admin.PulsarAdmin;
import org.apache.pulsar.client.admin.PulsarAdminException;
import org.apache.pulsar.client.api.Consumer;
@@ -48,6 +44,11 @@ import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.SizeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.ScopeType;
/**
* LoadSimulationClient is used to simulate client load by maintaining
producers and consumers for topics. Instances of
@@ -170,19 +171,20 @@ public class LoadSimulationClient {
}
}
- // JCommander arguments for starting a LoadSimulationClient.
- @Parameters(commandDescription = "Simulate client load by maintaining
producers and consumers for topics.")
+ // picocli arguments for starting a LoadSimulationClient.
+ @Command(description = "Simulate client load by maintaining producers and
consumers for topics.",
+ showDefaultValues = true, scope = ScopeType.INHERIT)
private static class MainArguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Help message", help
= true)
boolean help;
- @Parameter(names = { "--port" }, description = "Port to listen on for
controller", required = true)
+ @Option(names = { "--port" }, description = "Port to listen on for
controller", required = true)
public int port;
- @Parameter(names = { "--service-url" }, description = "Pulsar Service
URL", required = true)
+ @Option(names = { "--service-url" }, description = "Pulsar Service
URL", required = true)
public String serviceURL;
- @Parameter(names = { "-ml", "--memory-limit", }, description =
"Configure the Pulsar client memory limit "
+ @Option(names = { "-ml", "--memory-limit", }, description = "Configure
the Pulsar client memory limit "
+ "(eg: 32M, 64M)", converter = ByteUnitToLongConverter.class)
public long memoryLimit = 0L;
}
@@ -310,7 +312,7 @@ public class LoadSimulationClient {
private static final MessageListener<byte[]> ackListener =
Consumer::acknowledgeAsync;
/**
- * Create a LoadSimulationClient with the given JCommander arguments.
+ * Create a LoadSimulationClient with the given picocli arguments.
*
* @param arguments
* Arguments to configure this from.
@@ -341,13 +343,13 @@ public class LoadSimulationClient {
*/
public static void main(String[] args) throws Exception {
final MainArguments mainArguments = new MainArguments();
- final JCommander jc = new JCommander(mainArguments);
- jc.setProgramName("pulsar-perf simulation-client");
+ CommandLine commander = new CommandLine(mainArguments);
+ commander.setCommandName("pulsar-perf simulation-client");
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
PerfClientUtils.printJVMInformation(log);
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationController.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationController.java
index e967ba9e517..94186c581eb 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationController.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/LoadSimulationController.java
@@ -20,10 +20,6 @@ package org.apache.pulsar.testclient;
import static
org.apache.pulsar.broker.resources.LoadBalanceResources.BUNDLE_DATA_BASE_PATH;
import static
org.apache.pulsar.broker.resources.LoadBalanceResources.RESOURCE_QUOTA_BASE_PATH;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -56,6 +52,12 @@ import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.Parameters;
+import picocli.CommandLine.ScopeType;
/**
* This class provides a shell for the user to dictate how simulation clients
should incur load.
@@ -82,50 +84,50 @@ public class LoadSimulationController {
private static final ExecutorService threadPool =
Executors.newCachedThreadPool();
- // JCommander arguments for starting a controller via main.
- @Parameters(commandDescription = "Provides a shell for the user to dictate
how simulation clients should "
- + "incur load.")
+ // picocli arguments for starting a controller via main.
+ @Command(description = "Provides a shell for the user to dictate how
simulation clients should "
+ + "incur load.", showDefaultValues = true, scope =
ScopeType.INHERIT)
private static class MainArguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Help message", help
= true)
boolean help;
- @Parameter(names = { "--cluster" }, description = "Cluster to test
on", required = true)
+ @Option(names = { "--cluster" }, description = "Cluster to test on",
required = true)
String cluster;
- @Parameter(names = { "--clients" }, description = "Comma separated
list of client hostnames", required = true)
+ @Option(names = { "--clients" }, description = "Comma separated list
of client hostnames", required = true)
String clientHostNames;
- @Parameter(names = { "--client-port" }, description = "Port that the
clients are listening on", required = true)
+ @Option(names = { "--client-port" }, description = "Port that the
clients are listening on", required = true)
int clientPort;
}
- // JCommander arguments for accepting user input.
+ // picocli arguments for accepting user input.
private static class ShellArguments {
- @Parameter(description = "Command arguments:\n" + "trade tenant
namespace topic\n"
+ @Parameters(description = "Command arguments:\n" + "trade tenant
namespace topic\n"
+ "change tenant namespace topic\n" + "stop tenant namespace
topic\n"
+ "trade_group tenant group_name num_namespaces\n" +
"change_group tenant group_name\n"
+ "stop_group tenant group_name\n" + "script script_name\n" +
"copy tenant_name source_zk target_zk\n"
- + "stream source_zk\n" + "simulate zk\n", required = true)
+ + "stream source_zk\n" + "simulate zk\n", arity = "1")
List<String> commandArguments;
- @Parameter(names = { "--rand-rate" }, description = "Choose message
rate uniformly randomly from the next two "
+ @Option(names = { "--rand-rate" }, description = "Choose message rate
uniformly randomly from the next two "
+ "comma separated values (overrides --rate)")
String rangeString = "";
- @Parameter(names = { "--rate" }, description = "Messages per second")
+ @Option(names = { "--rate" }, description = "Messages per second")
double rate = 1;
- @Parameter(names = { "--rate-multiplier" }, description = "Multiplier
to use for copying or streaming rates")
+ @Option(names = { "--rate-multiplier" }, description = "Multiplier to
use for copying or streaming rates")
double rateMultiplier = 1;
- @Parameter(names = { "--separation" }, description = "Separation time
in ms for trade_group actions "
+ @Option(names = { "--separation" }, description = "Separation time in
ms for trade_group actions "
+ "(0 for no separation)")
int separation = 0;
- @Parameter(names = { "--size" }, description = "Message size in bytes")
+ @Option(names = { "--size" }, description = "Message size in bytes")
int size = 1024;
- @Parameter(names = { "--topics-per-namespace" }, description = "Number
of topics to create per namespace in "
+ @Option(names = { "--topics-per-namespace" }, description = "Number of
topics to create per namespace in "
+ "trade_group (total number of topics is num_namespaces X
num_topics)")
int topicsPerNamespace = 1;
}
@@ -212,7 +214,7 @@ public class LoadSimulationController {
}
/**
- * Create a LoadSimulationController with the given JCommander arguments.
+ * Create a LoadSimulationController with the given picocli arguments.
*
* @param arguments
* Arguments to create from.
@@ -318,7 +320,7 @@ public class LoadSimulationController {
outputStream.writeDouble(arguments.rate);
}
- // Change producer settings for a given topic and JCommander arguments.
+ // Change producer settings for a given topic and picocli arguments.
private void change(final ShellArguments arguments, final String topic,
final int client) throws Exception {
outputStreams[client].write(LoadSimulationClient.CHANGE_COMMAND);
writeProducerOptions(outputStreams[client], arguments, topic);
@@ -360,7 +362,7 @@ public class LoadSimulationController {
return clientWithTopic;
}
- // Trade using the arguments parsed via JCommander and the topic name.
+ // Trade using the arguments parsed via picocli and the topic name.
private synchronized void trade(final ShellArguments arguments, final
String topic, final int client)
throws Exception {
// Decide which client to send to randomly to preserve statelessness of
@@ -632,9 +634,9 @@ public class LoadSimulationController {
// Don't attempt to process blank input.
if (args.length > 0 && !(args.length == 1 && args[0].isEmpty())) {
final ShellArguments arguments = new ShellArguments();
- final JCommander jc = new JCommander(arguments);
+ final CommandLine commander = new CommandLine(arguments);
try {
- jc.parse(args);
+ commander.parseArgs(args);
final String command = arguments.commandArguments.get(0);
switch (command) {
case "trade":
@@ -687,8 +689,8 @@ public class LoadSimulationController {
log.info("ERROR: Unknown command \"{}\"", command);
}
} catch (ParameterException ex) {
- ex.printStackTrace();
- jc.usage();
+ System.out.println(ex.getMessage());
+ commander.usage(commander.getOut());
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -716,13 +718,13 @@ public class LoadSimulationController {
*/
public static void main(String[] args) throws Exception {
final MainArguments arguments = new MainArguments();
- final JCommander jc = new JCommander(arguments);
- jc.setProgramName("pulsar-perf simulation-controller");
+ final CommandLine commander = new CommandLine(arguments);
+ commander.setCommandName("pulsar-perf simulation-controller");
try {
- jc.parse(args);
- } catch (Exception ex) {
- System.out.println(ex.getMessage());
- jc.usage();
+ commander.parseArgs(args);
+ } catch (ParameterException e) {
+ System.out.println(e.getMessage());
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
(new LoadSimulationController(arguments)).run();
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/ManagedLedgerWriter.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/ManagedLedgerWriter.java
index 336461e7a68..bad8e56a638 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/ManagedLedgerWriter.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/ManagedLedgerWriter.java
@@ -19,10 +19,6 @@
package org.apache.pulsar.testclient;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
-import com.beust.jcommander.Parameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.util.concurrent.RateLimiter;
@@ -64,6 +60,11 @@ import
org.apache.pulsar.metadata.api.extended.MetadataStoreExtended;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
+import picocli.CommandLine.ScopeType;
public class ManagedLedgerWriter {
@@ -78,61 +79,61 @@ public class ManagedLedgerWriter {
private static Recorder recorder = new
Recorder(TimeUnit.SECONDS.toMillis(120000), 5);
private static Recorder cumulativeRecorder = new
Recorder(TimeUnit.SECONDS.toMillis(120000), 5);
- @Parameters(commandDescription = "Write directly on managed-ledgers")
+ @Command(description = "Write directly on managed-ledgers",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments {
- @Parameter(names = { "-h", "--help" }, description = "Help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Help message", help
= true)
boolean help;
- @Parameter(names = { "-r", "--rate" }, description = "Write rate msg/s
across managed ledgers")
+ @Option(names = { "-r", "--rate" }, description = "Write rate msg/s
across managed ledgers")
public int msgRate = 100;
- @Parameter(names = { "-s", "--size" }, description = "Message size")
+ @Option(names = { "-s", "--size" }, description = "Message size")
public int msgSize = 1024;
- @Parameter(names = { "-t", "--num-topic" },
- description = "Number of managed ledgers", validateWith =
PositiveNumberParameterValidator.class)
+ @Option(names = { "-t", "--num-topic" },
+ description = "Number of managed ledgers", converter =
PositiveNumberParameterConvert.class)
public int numManagedLedgers = 1;
- @Parameter(names = { "--threads" },
- description = "Number of threads writing", validateWith =
PositiveNumberParameterValidator.class)
+ @Option(names = { "--threads" },
+ description = "Number of threads writing", converter =
PositiveNumberParameterConvert.class)
public int numThreads = 1;
@Deprecated
- @Parameter(names = {"-zk", "--zookeeperServers"},
+ @Option(names = {"-zk", "--zookeeperServers"},
description = "ZooKeeper connection string",
hidden = true)
public String zookeeperServers;
- @Parameter(names = {"-md",
+ @Option(names = {"-md",
"--metadata-store"}, description = "Metadata store service
URL. For example: zk:my-zk:2181")
private String metadataStoreUrl;
- @Parameter(names = { "-o", "--max-outstanding" }, description = "Max
number of outstanding requests")
+ @Option(names = { "-o", "--max-outstanding" }, description = "Max
number of outstanding requests")
public int maxOutstanding = 1000;
- @Parameter(names = { "-c",
+ @Option(names = { "-c",
"--max-connections" }, description = "Max number of TCP
connections to a single bookie")
public int maxConnections = 1;
- @Parameter(names = { "-m",
+ @Option(names = { "-m",
"--num-messages" },
description = "Number of messages to publish in total. If <=
0, it will keep publishing")
public long numMessages = 0;
- @Parameter(names = { "-e", "--ensemble-size" }, description = "Ledger
ensemble size")
+ @Option(names = { "-e", "--ensemble-size" }, description = "Ledger
ensemble size")
public int ensembleSize = 1;
- @Parameter(names = { "-w", "--write-quorum" }, description = "Ledger
write quorum")
+ @Option(names = { "-w", "--write-quorum" }, description = "Ledger
write quorum")
public int writeQuorum = 1;
- @Parameter(names = { "-a", "--ack-quorum" }, description = "Ledger ack
quorum")
+ @Option(names = { "-a", "--ack-quorum" }, description = "Ledger ack
quorum")
public int ackQuorum = 1;
- @Parameter(names = { "-dt", "--digest-type" }, description =
"BookKeeper digest type")
+ @Option(names = { "-dt", "--digest-type" }, description = "BookKeeper
digest type")
public DigestType digestType = DigestType.CRC32C;
- @Parameter(names = { "-time",
+ @Option(names = { "-time",
"--test-duration" }, description = "Test duration in secs. If
<= 0, it will keep publishing")
public long testTime = 0;
@@ -141,25 +142,25 @@ public class ManagedLedgerWriter {
public static void main(String[] args) throws Exception {
final Arguments arguments = new Arguments();
- JCommander jc = new JCommander(arguments);
- jc.setProgramName("pulsar-perf managed-ledger");
+ CommandLine commander = new CommandLine(arguments);
+ commander.setCommandName("pulsar-perf managed-ledger");
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
System.out.println(e.getMessage());
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
if (arguments.help) {
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
if (arguments.metadataStoreUrl == null && arguments.zookeeperServers
== null) {
System.err.println("Metadata store address argument is required
(--metadata-store)");
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
index bc4ab003c46..d320cafc1a0 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
@@ -20,16 +20,16 @@ package org.apache.pulsar.testclient;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.pulsar.testclient.PerfClientUtils.exit;
-import com.beust.jcommander.JCommander;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
-import org.apache.pulsar.cli.converters.ByteUnitToLongConverter;
+import org.apache.pulsar.cli.converters.picocli.ByteUnitToLongConverter;
import org.apache.pulsar.client.api.ProxyProtocol;
+import picocli.CommandLine;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ParameterException;
/**
* PerformanceBaseArguments contains common CLI arguments and parsing logic
available to all sub-commands.
@@ -37,74 +37,74 @@ import org.apache.pulsar.client.api.ProxyProtocol;
*/
public abstract class PerformanceBaseArguments {
- @Parameter(names = { "-h", "--help" }, description = "Print help message",
help = true)
+ @Option(names = { "-h", "--help" }, description = "Print help message",
help = true)
boolean help;
- @Parameter(names = { "-cf", "--conf-file" }, description = "Pulsar
configuration file")
+ @Option(names = { "-cf", "--conf-file" }, description = "Pulsar
configuration file")
public String confFile;
- @Parameter(names = { "-u", "--service-url" }, description = "Pulsar
Service URL")
+ @Option(names = { "-u", "--service-url" }, description = "Pulsar Service
URL")
public String serviceURL;
- @Parameter(names = { "--auth-plugin" }, description = "Authentication
plugin class name")
+ @Option(names = { "--auth-plugin" }, description = "Authentication plugin
class name")
public String authPluginClassName;
- @Parameter(
+ @Option(
names = { "--auth-params" },
description = "Authentication parameters, whose format is
determined by the implementation "
+ "of method `configure` in authentication plugin class,
for example \"key1:val1,key2:val2\" "
+ "or \"{\"key1\":\"val1\",\"key2\":\"val2\"}\".")
public String authParams;
- @Parameter(names = {
+ @Option(names = {
"--trust-cert-file" }, description = "Path for the trusted TLS
certificate file")
public String tlsTrustCertsFilePath = "";
- @Parameter(names = {
+ @Option(names = {
"--tls-allow-insecure" }, description = "Allow insecure TLS
connection")
public Boolean tlsAllowInsecureConnection = null;
- @Parameter(names = {
+ @Option(names = {
"--tls-enable-hostname-verification" }, description = "Enable TLS
hostname verification")
public Boolean tlsHostnameVerificationEnable = null;
- @Parameter(names = { "-c",
+ @Option(names = { "-c",
"--max-connections" }, description = "Max number of TCP
connections to a single broker")
public int maxConnections = 1;
- @Parameter(names = { "-i",
+ @Option(names = { "-i",
"--stats-interval-seconds" },
description = "Statistics Interval Seconds. If 0, statistics will
be disabled")
public long statsIntervalSeconds = 0;
- @Parameter(names = {"-ioThreads", "--num-io-threads"}, description = "Set
the number of threads to be "
+ @Option(names = {"-ioThreads", "--num-io-threads"}, description = "Set the
number of threads to be "
+ "used for handling connections to brokers. The default value is
1.")
public int ioThreads = 1;
- @Parameter(names = {"-bw", "--busy-wait"}, description = "Enable Busy-Wait
on the Pulsar client")
+ @Option(names = {"-bw", "--busy-wait"}, description = "Enable Busy-Wait on
the Pulsar client")
public boolean enableBusyWait = false;
- @Parameter(names = { "--listener-name" }, description = "Listener name for
the broker.")
+ @Option(names = { "--listener-name" }, description = "Listener name for
the broker.")
public String listenerName = null;
- @Parameter(names = {"-lt", "--num-listener-threads"}, description = "Set
the number of threads"
+ @Option(names = {"-lt", "--num-listener-threads"}, description = "Set the
number of threads"
+ " to be used for message listeners")
public int listenerThreads = 1;
- @Parameter(names = {"-mlr", "--max-lookup-request"}, description =
"Maximum number of lookup requests allowed "
+ @Option(names = {"-mlr", "--max-lookup-request"}, description = "Maximum
number of lookup requests allowed "
+ "on each broker connection to prevent overloading a broker")
public int maxLookupRequest = 50000;
- @Parameter(names = { "--proxy-url" }, description = "Proxy-server URL to
which to connect.")
+ @Option(names = { "--proxy-url" }, description = "Proxy-server URL to
which to connect.")
String proxyServiceURL = null;
- @Parameter(names = { "--proxy-protocol" }, description = "Proxy protocol
to select type of routing at proxy.")
+ @Option(names = { "--proxy-protocol" }, description = "Proxy protocol to
select type of routing at proxy.")
ProxyProtocol proxyProtocol = null;
- @Parameter(names = { "--auth_plugin" }, description = "Authentication
plugin class name", hidden = true)
+ @Option(names = { "--auth_plugin" }, description = "Authentication plugin
class name", hidden = true)
public String deprecatedAuthPluginClassName;
- @Parameter(names = { "-ml", "--memory-limit", }, description = "Configure
the Pulsar client memory limit "
+ @Option(names = { "-ml", "--memory-limit", }, description = "Configure the
Pulsar client memory limit "
+ "(eg: 32M, 64M)", converter = ByteUnitToLongConverter.class)
public long memoryLimit;
@@ -203,19 +203,18 @@ public abstract class PerformanceBaseArguments {
* @throws ParameterException If there is a problem parsing the arguments
*/
public void parseCLI(String cmdName, String[] args) {
- JCommander jc = new JCommander(this);
- jc.setProgramName(cmdName);
-
+ CommandLine commander = new CommandLine(this);
+ commander.setCommandName(cmdName);
try {
- jc.parse(args);
+ commander.parseArgs(args);
} catch (ParameterException e) {
- System.out.println("error: " + e.getMessage());
- jc.usage();
+ System.out.println(e.getMessage());
+ commander.usage(commander.getOut());
PerfClientUtils.exit(1);
}
if (help) {
- jc.usage();
+ commander.usage(commander.getOut());
PerfClientUtils.exit(0);
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
index 7863bc49a15..7a2bc4382fd 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
@@ -19,8 +19,6 @@
package org.apache.pulsar.testclient;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.util.concurrent.RateLimiter;
@@ -57,6 +55,9 @@ import org.apache.pulsar.common.naming.TopicName;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ScopeType;
public class PerformanceConsumer {
private static final LongAdder messagesReceived = new LongAdder();
@@ -82,105 +83,107 @@ public class PerformanceConsumer {
private static final Recorder recorder = new Recorder(MAX_LATENCY, 5);
private static final Recorder cumulativeRecorder = new
Recorder(MAX_LATENCY, 5);
- @Parameters(commandDescription = "Test pulsar consumer performance.")
+ @Command(description = "Test pulsar consumer performance.",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments extends PerformanceTopicListArguments {
- @Parameter(names = { "-n", "--num-consumers" }, description = "Number
of consumers (per subscription), only "
+ @Option(names = { "-n", "--num-consumers" }, description = "Number of
consumers (per subscription), only "
+ "one consumer is allowed when subscriptionType is Exclusive",
- validateWith = PositiveNumberParameterValidator.class)
+ converter = PositiveNumberParameterConvert.class
+ )
public int numConsumers = 1;
- @Parameter(names = { "-ns", "--num-subscriptions" }, description =
"Number of subscriptions (per topic)",
- validateWith = PositiveNumberParameterValidator.class)
+ @Option(names = { "-ns", "--num-subscriptions" }, description =
"Number of subscriptions (per topic)",
+ converter = PositiveNumberParameterConvert.class
+ )
public int numSubscriptions = 1;
- @Parameter(names = { "-s", "--subscriber-name" }, description =
"Subscriber name prefix", hidden = true)
+ @Option(names = { "-s", "--subscriber-name" }, description =
"Subscriber name prefix", hidden = true)
public String subscriberName;
- @Parameter(names = { "-ss", "--subscriptions" },
+ @Option(names = { "-ss", "--subscriptions" },
description = "A list of subscriptions to consume (for
example, sub1,sub2)")
public List<String> subscriptions = Collections.singletonList("sub");
- @Parameter(names = { "-st", "--subscription-type" }, description =
"Subscription type")
+ @Option(names = { "-st", "--subscription-type" }, description =
"Subscription type")
public SubscriptionType subscriptionType = SubscriptionType.Exclusive;
- @Parameter(names = { "-sp", "--subscription-position" }, description =
"Subscription position")
+ @Option(names = { "-sp", "--subscription-position" }, description =
"Subscription position")
private SubscriptionInitialPosition subscriptionInitialPosition =
SubscriptionInitialPosition.Latest;
- @Parameter(names = { "-r", "--rate" }, description = "Simulate a slow
message consumer (rate in msg/s)")
+ @Option(names = { "-r", "--rate" }, description = "Simulate a slow
message consumer (rate in msg/s)")
public double rate = 0;
- @Parameter(names = { "-q", "--receiver-queue-size" }, description =
"Size of the receiver queue")
+ @Option(names = { "-q", "--receiver-queue-size" }, description = "Size
of the receiver queue")
public int receiverQueueSize = 1000;
- @Parameter(names = { "-p", "--receiver-queue-size-across-partitions" },
+ @Option(names = { "-p", "--receiver-queue-size-across-partitions" },
description = "Max total size of the receiver queue across
partitions")
public int maxTotalReceiverQueueSizeAcrossPartitions = 50000;
- @Parameter(names = {"-aq", "--auto-scaled-receiver-queue-size"},
+ @Option(names = {"-aq", "--auto-scaled-receiver-queue-size"},
description = "Enable autoScaledReceiverQueueSize")
public boolean autoScaledReceiverQueueSize = false;
- @Parameter(names = {"-rs", "--replicated" },
+ @Option(names = {"-rs", "--replicated" },
description = "Whether the subscription status should be
replicated")
public boolean replicatedSubscription = false;
- @Parameter(names = { "--acks-delay-millis" }, description =
"Acknowledgements grouping delay in millis")
+ @Option(names = { "--acks-delay-millis" }, description =
"Acknowledgements grouping delay in millis")
public int acknowledgmentsGroupingDelayMillis = 100;
- @Parameter(names = {"-m",
+ @Option(names = {"-m",
"--num-messages"},
description = "Number of messages to consume in total. If <=
0, it will keep consuming")
public long numMessages = 0;
- @Parameter(names = { "-mc", "--max_chunked_msg" }, description = "Max
pending chunk messages")
+ @Option(names = { "-mc", "--max_chunked_msg" }, description = "Max
pending chunk messages")
private int maxPendingChunkedMessage = 0;
- @Parameter(names = { "-ac",
+ @Option(names = { "-ac",
"--auto_ack_chunk_q_full" }, description = "Auto ack for
oldest message on queue is full")
private boolean autoAckOldestChunkedMessageOnQueueFull = false;
- @Parameter(names = { "-e",
+ @Option(names = { "-e",
"--expire_time_incomplete_chunked_messages" },
description = "Expire time in ms for incomplete chunk
messages")
private long expireTimeOfIncompleteChunkedMessageMs = 0;
- @Parameter(names = { "-v",
+ @Option(names = { "-v",
"--encryption-key-value-file" },
description = "The file which contains the private key to
decrypt payload")
public String encKeyFile = null;
- @Parameter(names = { "-time",
+ @Option(names = { "-time",
"--test-duration" }, description = "Test duration in secs. If
<= 0, it will keep consuming")
public long testTime = 0;
- @Parameter(names = {"--batch-index-ack" }, description = "Enable or
disable the batch index acknowledgment")
+ @Option(names = {"--batch-index-ack" }, description = "Enable or
disable the batch index acknowledgment")
public boolean batchIndexAck = false;
- @Parameter(names = { "-pm", "--pool-messages" }, description = "Use
the pooled message", arity = 1)
+ @Option(names = { "-pm", "--pool-messages" }, description = "Use the
pooled message", arity = "1")
private boolean poolMessages = true;
- @Parameter(names = {"-tto", "--txn-timeout"}, description = "Set the
time value of transaction timeout,"
+ @Option(names = {"-tto", "--txn-timeout"}, description = "Set the
time value of transaction timeout,"
+ " and the time unit is second. (After --txn-enable setting
to true, --txn-timeout takes effect)")
public long transactionTimeout = 10;
- @Parameter(names = {"-nmt", "--numMessage-perTransaction"},
+ @Option(names = {"-nmt", "--numMessage-perTransaction"},
description = "The number of messages acknowledged by a
transaction. "
+ "(After --txn-enable setting to true,
-numMessage-perTransaction takes effect")
public int numMessagesPerTransaction = 50;
- @Parameter(names = {"-txn", "--txn-enable"}, description = "Enable or
disable the transaction")
+ @Option(names = {"-txn", "--txn-enable"}, description = "Enable or
disable the transaction")
public boolean isEnableTransaction = false;
- @Parameter(names = {"-ntxn"}, description = "The number of opened
transactions, 0 means keeping open."
+ @Option(names = {"-ntxn"}, description = "The number of opened
transactions, 0 means keeping open."
+ "(After --txn-enable setting to true, -ntxn takes effect.)")
public long totalNumTxn = 0;
- @Parameter(names = {"-abort"}, description = "Abort the transaction.
(After --txn-enable "
+ @Option(names = {"-abort"}, description = "Abort the transaction.
(After --txn-enable "
+ "setting to true, -abort takes effect)")
public boolean isAbortTransaction = false;
- @Parameter(names = { "--histogram-file" }, description = "HdrHistogram
output file")
+ @Option(names = { "--histogram-file" }, description = "HdrHistogram
output file")
public String histogramFile = null;
@Override
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
index ac34bbd9f7a..0eb8d02f31e 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
@@ -25,9 +25,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_BATCHING_MAX_MESSAGES;
import static
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_MAX_PENDING_MESSAGES;
import static
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_MAX_PENDING_MESSAGES_ACROSS_PARTITIONS;
-import com.beust.jcommander.IStringConverter;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.collect.Range;
@@ -75,6 +72,11 @@ import
org.apache.pulsar.common.partition.PartitionedTopicMetadata;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.ITypeConverter;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ScopeType;
+import picocli.CommandLine.TypeConversionException;
/**
* A client program to test pulsar producer performance.
@@ -103,151 +105,153 @@ public class PerformanceProducer {
private static IMessageFormatter messageFormatter = null;
- @Parameters(commandDescription = "Test pulsar producer performance.")
+ @Command(description = "Test pulsar producer performance.",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments extends PerformanceTopicListArguments {
- @Parameter(names = { "-threads", "--num-test-threads" }, description =
"Number of test threads",
- validateWith = PositiveNumberParameterValidator.class)
+ @Option(names = { "-threads", "--num-test-threads" }, description =
"Number of test threads",
+ converter = PositiveNumberParameterConvert.class
+ )
public int numTestThreads = 1;
- @Parameter(names = { "-r", "--rate" }, description = "Publish rate
msg/s across topics")
+ @Option(names = { "-r", "--rate" }, description = "Publish rate msg/s
across topics")
public int msgRate = 100;
- @Parameter(names = { "-s", "--size" }, description = "Message size
(bytes)")
+ @Option(names = { "-s", "--size" }, description = "Message size
(bytes)")
public int msgSize = 1024;
- @Parameter(names = { "-n", "--num-producers" }, description = "Number
of producers (per topic)",
- validateWith = PositiveNumberParameterValidator.class)
+ @Option(names = { "-n", "--num-producers" }, description = "Number of
producers (per topic)",
+ converter = PositiveNumberParameterConvert.class
+ )
public int numProducers = 1;
- @Parameter(names = {"--separator"}, description = "Separator between
the topic and topic number")
+ @Option(names = {"--separator"}, description = "Separator between the
topic and topic number")
public String separator = "-";
- @Parameter(names = {"--send-timeout"}, description = "Set the
sendTimeout value default 0 to keep "
+ @Option(names = {"--send-timeout"}, description = "Set the sendTimeout
value default 0 to keep "
+ "compatibility with previous version of pulsar-perf")
public int sendTimeout = 0;
- @Parameter(names = { "-pn", "--producer-name" }, description =
"Producer Name")
+ @Option(names = { "-pn", "--producer-name" }, description = "Producer
Name")
public String producerName = null;
- @Parameter(names = { "-au", "--admin-url" }, description = "Pulsar
Admin URL")
+ @Option(names = { "-au", "--admin-url" }, description = "Pulsar Admin
URL")
public String adminURL;
- @Parameter(names = { "-ch",
+ @Option(names = { "-ch",
"--chunking" }, description = "Should split the message and
publish in chunks if message size is "
+ "larger than allowed max size")
private boolean chunkingAllowed = false;
- @Parameter(names = { "-o", "--max-outstanding" }, description = "Max
number of outstanding messages")
+ @Option(names = { "-o", "--max-outstanding" }, description = "Max
number of outstanding messages")
public int maxOutstanding = DEFAULT_MAX_PENDING_MESSAGES;
- @Parameter(names = { "-p", "--max-outstanding-across-partitions" },
description = "Max number of outstanding "
+ @Option(names = { "-p", "--max-outstanding-across-partitions" },
description = "Max number of outstanding "
+ "messages across partitions")
public int maxPendingMessagesAcrossPartitions =
DEFAULT_MAX_PENDING_MESSAGES_ACROSS_PARTITIONS;
- @Parameter(names = { "-np", "--partitions" }, description = "Create
partitioned topics with the given number "
+ @Option(names = { "-np", "--partitions" }, description = "Create
partitioned topics with the given number "
+ "of partitions, set 0 to not try to create the topic")
public Integer partitions = null;
- @Parameter(names = { "-m",
+ @Option(names = { "-m",
"--num-messages" }, description = "Number of messages to
publish in total. If <= 0, it will keep "
+ "publishing")
public long numMessages = 0;
- @Parameter(names = { "-z", "--compression" }, description = "Compress
messages payload")
+ @Option(names = { "-z", "--compression" }, description = "Compress
messages payload")
public CompressionType compression = CompressionType.NONE;
- @Parameter(names = { "-f", "--payload-file" }, description = "Use
payload from an UTF-8 encoded text file and "
+ @Option(names = { "-f", "--payload-file" }, description = "Use payload
from an UTF-8 encoded text file and "
+ "a payload will be randomly selected when publishing
messages")
public String payloadFilename = null;
- @Parameter(names = { "-e", "--payload-delimiter" }, description = "The
delimiter used to split lines when "
+ @Option(names = { "-e", "--payload-delimiter" }, description = "The
delimiter used to split lines when "
+ "using payload from a file")
// here escaping \n since default value will be printed with the help
text
public String payloadDelimiter = "\\n";
- @Parameter(names = { "-b",
+ @Option(names = { "-b",
"--batch-time-window" }, description = "Batch messages in 'x'
ms window (Default: 1ms)")
public double batchTimeMillis = 1.0;
- @Parameter(names = { "-db",
+ @Option(names = { "-db",
"--disable-batching" }, description = "Disable batching if
true")
public boolean disableBatching;
- @Parameter(names = {
+ @Option(names = {
"-bm", "--batch-max-messages"
}, description = "Maximum number of messages per batch")
public int batchMaxMessages = DEFAULT_BATCHING_MAX_MESSAGES;
- @Parameter(names = {
+ @Option(names = {
"-bb", "--batch-max-bytes"
}, description = "Maximum number of bytes per batch")
public int batchMaxBytes = 4 * 1024 * 1024;
- @Parameter(names = { "-time",
+ @Option(names = { "-time",
"--test-duration" }, description = "Test duration in secs. If
<= 0, it will keep publishing")
public long testTime = 0;
- @Parameter(names = "--warmup-time", description = "Warm-up time in
seconds (Default: 1 sec)")
+ @Option(names = "--warmup-time", description = "Warm-up time in
seconds (Default: 1 sec)")
public double warmupTimeSeconds = 1.0;
- @Parameter(names = { "-k", "--encryption-key-name" }, description =
"The public key name to encrypt payload")
+ @Option(names = { "-k", "--encryption-key-name" }, description = "The
public key name to encrypt payload")
public String encKeyName = null;
- @Parameter(names = { "-v",
+ @Option(names = { "-v",
"--encryption-key-value-file" },
description = "The file which contains the public key to
encrypt payload")
public String encKeyFile = null;
- @Parameter(names = { "-d",
+ @Option(names = { "-d",
"--delay" }, description = "Mark messages with a given delay
in seconds")
public long delay = 0;
- @Parameter(names = { "-dr", "--delay-range"}, description = "Mark
messages with a given delay by a random"
+ @Option(names = { "-dr", "--delay-range"}, description = "Mark
messages with a given delay by a random"
+ " number of seconds. this value between the specified origin
(inclusive) and the specified bound"
+ " (exclusive). e.g. 1,300", converter = RangeConvert.class)
public Range<Long> delayRange = null;
- @Parameter(names = { "-set",
+ @Option(names = { "-set",
"--set-event-time" }, description = "Set the eventTime on
messages")
public boolean setEventTime = false;
- @Parameter(names = { "-ef",
+ @Option(names = { "-ef",
"--exit-on-failure" }, description = "Exit from the process on
publish failure (default: disable)")
public boolean exitOnFailure = false;
- @Parameter(names = {"-mk", "--message-key-generation-mode"},
description = "The generation mode of message key"
+ @Option(names = {"-mk", "--message-key-generation-mode"}, description
= "The generation mode of message key"
+ ", valid options are: [autoIncrement, random]")
public String messageKeyGenerationMode = null;
- @Parameter(names = { "-am", "--access-mode" }, description = "Producer
access mode")
+ @Option(names = { "-am", "--access-mode" }, description = "Producer
access mode")
public ProducerAccessMode producerAccessMode =
ProducerAccessMode.Shared;
- @Parameter(names = { "-fp", "--format-payload" },
- description = "Format %i as a message index in the stream from
producer and/or %t as the timestamp"
+ @Option(names = { "-fp", "--format-payload" },
+ description = "Format %%i as a message index in the stream
from producer and/or %%t as the timestamp"
+ " nanoseconds.")
public boolean formatPayload = false;
- @Parameter(names = {"-fc", "--format-class"}, description = "Custom
Formatter class name")
+ @Option(names = {"-fc", "--format-class"}, description = "Custom
Formatter class name")
public String formatterClass =
"org.apache.pulsar.testclient.DefaultMessageFormatter";
- @Parameter(names = {"-tto", "--txn-timeout"}, description = "Set the
time value of transaction timeout,"
+ @Option(names = {"-tto", "--txn-timeout"}, description = "Set the time
value of transaction timeout,"
+ " and the time unit is second. (After --txn-enable setting
to true, --txn-timeout takes effect)")
public long transactionTimeout = 10;
- @Parameter(names = {"-nmt", "--numMessage-perTransaction"},
+ @Option(names = {"-nmt", "--numMessage-perTransaction"},
description = "The number of messages sent by a transaction. "
+ "(After --txn-enable setting to true, -nmt takes
effect)")
public int numMessagesPerTransaction = 50;
- @Parameter(names = {"-txn", "--txn-enable"}, description = "Enable or
disable the transaction")
+ @Option(names = {"-txn", "--txn-enable"}, description = "Enable or
disable the transaction")
public boolean isEnableTransaction = false;
- @Parameter(names = {"-abort"}, description = "Abort the transaction.
(After --txn-enable "
+ @Option(names = {"-abort"}, description = "Abort the transaction.
(After --txn-enable "
+ "setting to true, -abort takes effect)")
public boolean isAbortTransaction = false;
- @Parameter(names = { "--histogram-file" }, description = "HdrHistogram
output file")
+ @Option(names = { "--histogram-file" }, description = "HdrHistogram
output file")
public String histogramFile = null;
@Override
@@ -794,7 +798,7 @@ public class PerformanceProducer {
autoIncrement, random
}
- static class RangeConvert implements IStringConverter<Range<Long>> {
+ static class RangeConvert implements ITypeConverter<Range<Long>> {
@Override
public Range<Long> convert(String rangeStr) {
try {
@@ -804,7 +808,7 @@ public class PerformanceProducer {
final long max = Long.parseLong(facts[1].trim());
return Range.closedOpen(min, max);
} catch (Throwable ex) {
- throw new IllegalArgumentException("Unknown delay range
interval,"
+ throw new TypeConversionException("Unknown delay range
interval,"
+ " the format should be \"<origin>,<bound>\". error
message: " + rangeStr);
}
}
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
index ed5cc37644a..3572cbde43c 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
@@ -18,8 +18,6 @@
*/
package org.apache.pulsar.testclient;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.util.concurrent.RateLimiter;
@@ -46,6 +44,9 @@ import org.apache.pulsar.common.util.FutureUtil;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ScopeType;
public class PerformanceReader {
private static final LongAdder messagesReceived = new LongAdder();
@@ -59,30 +60,30 @@ public class PerformanceReader {
private static Recorder recorder = new
Recorder(TimeUnit.DAYS.toMillis(10), 5);
private static Recorder cumulativeRecorder = new
Recorder(TimeUnit.DAYS.toMillis(10), 5);
- @Parameters(commandDescription = "Test pulsar reader performance.")
+ @Command(description = "Test pulsar reader performance.",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments extends PerformanceTopicListArguments {
- @Parameter(names = { "-r", "--rate" }, description = "Simulate a slow
message reader (rate in msg/s)")
+ @Option(names = { "-r", "--rate" }, description = "Simulate a slow
message reader (rate in msg/s)")
public double rate = 0;
- @Parameter(names = { "-m",
+ @Option(names = { "-m",
"--start-message-id" }, description = "Start message id. This
can be either 'earliest', "
+ "'latest' or a specific message id by using 'lid:eid'")
public String startMessageId = "earliest";
- @Parameter(names = { "-q", "--receiver-queue-size" }, description =
"Size of the receiver queue")
+ @Option(names = { "-q", "--receiver-queue-size" }, description = "Size
of the receiver queue")
public int receiverQueueSize = 1000;
- @Parameter(names = {"-n",
+ @Option(names = {"-n",
"--num-messages"}, description = "Number of messages to
consume in total. If <= 0, "
+ "it will keep consuming")
public long numMessages = 0;
- @Parameter(names = {
+ @Option(names = {
"--use-tls" }, description = "Use TLS encryption on the
connection")
public boolean useTls;
- @Parameter(names = { "-time",
+ @Option(names = { "-time",
"--test-duration" }, description = "Test duration in secs. If
<= 0, it will keep consuming")
public long testTime = 0;
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
index a2f8b6af082..9ac99d0abcc 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
@@ -18,10 +18,11 @@
*/
package org.apache.pulsar.testclient;
-import com.beust.jcommander.Parameter;
import java.util.ArrayList;
import java.util.List;
import org.apache.pulsar.common.naming.TopicName;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
/**
* PerformanceTopicListArguments provides common topic list arguments which
are used
@@ -29,12 +30,13 @@ import org.apache.pulsar.common.naming.TopicName;
*/
public abstract class PerformanceTopicListArguments extends
PerformanceBaseArguments {
- @Parameter(description = "persistent://prop/ns/my-topic", required = true)
+ @Parameters(description = "persistent://prop/ns/my-topic", arity = "1")
public List<String> topics;
- @Parameter(names = { "-t", "--num-topics", "--num-topic" }, description =
"Number of topics. Must match"
+ @Option(names = { "-t", "--num-topics", "--num-topic" }, description =
"Number of topics. Must match"
+ "the given number of topic arguments.",
- validateWith = PositiveNumberParameterValidator.class)
+ converter = PositiveNumberParameterConvert.class
+ )
public int numTopics = 1;
@Override
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
index 0bfa216c459..02e50ab4e2b 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
@@ -19,8 +19,6 @@
package org.apache.pulsar.testclient;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.util.concurrent.RateLimiter;
@@ -65,6 +63,9 @@ import
org.apache.pulsar.common.partition.PartitionedTopicMetadata;
import org.apache.pulsar.testclient.utils.PaddingDecimalFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.ScopeType;
public class PerformanceTransaction {
@@ -89,84 +90,84 @@ public class PerformanceTransaction {
private static final Recorder messageSendRCumulativeRecorder =
new Recorder(TimeUnit.SECONDS.toMicros(120000), 5);
- @Parameters(commandDescription = "Test pulsar transaction performance.")
+ @Command(description = "Test pulsar transaction performance.",
showDefaultValues = true, scope = ScopeType.INHERIT)
static class Arguments extends PerformanceBaseArguments {
- @Parameter(names = "--topics-c", description = "All topics that need
ack for a transaction", required =
+ @Option(names = "--topics-c", description = "All topics that need ack
for a transaction", required =
true)
public List<String> consumerTopic =
Collections.singletonList("test-consume");
- @Parameter(names = "--topics-p", description = "All topics that need
produce for a transaction",
+ @Option(names = "--topics-p", description = "All topics that need
produce for a transaction",
required = true)
public List<String> producerTopic =
Collections.singletonList("test-produce");
- @Parameter(names = {"-threads", "--num-test-threads"}, description =
"Number of test threads."
+ @Option(names = {"-threads", "--num-test-threads"}, description =
"Number of test threads."
+ "This thread is for a new transaction to ack messages from
consumer topics and produce message to "
+ "producer topics, and then commit or abort this transaction.
"
+ "Increasing the number of threads increases the parallelism
of the performance test, "
+ "thereby increasing the intensity of the stress test.")
public int numTestThreads = 1;
- @Parameter(names = {"-au", "--admin-url"}, description = "Pulsar Admin
URL")
+ @Option(names = {"-au", "--admin-url"}, description = "Pulsar Admin
URL")
public String adminURL;
- @Parameter(names = {"-np",
+ @Option(names = {"-np",
"--partitions"}, description = "Create partitioned topics with
a given number of partitions, 0 means"
+ "not trying to create a topic")
public Integer partitions = null;
- @Parameter(names = {"-time",
+ @Option(names = {"-time",
"--test-duration"}, description = "Test duration (in second).
0 means keeping publishing")
public long testTime = 0;
- @Parameter(names = {"-ss",
+ @Option(names = {"-ss",
"--subscriptions"}, description = "A list of subscriptions to
consume (for example, sub1,sub2)")
public List<String> subscriptions = Collections.singletonList("sub");
- @Parameter(names = {"-ns", "--num-subscriptions"}, description =
"Number of subscriptions (per topic)")
+ @Option(names = {"-ns", "--num-subscriptions"}, description = "Number
of subscriptions (per topic)")
public int numSubscriptions = 1;
- @Parameter(names = {"-sp", "--subscription-position"}, description =
"Subscription position")
+ @Option(names = {"-sp", "--subscription-position"}, description =
"Subscription position")
private SubscriptionInitialPosition subscriptionInitialPosition =
SubscriptionInitialPosition.Earliest;
- @Parameter(names = {"-st", "--subscription-type"}, description =
"Subscription type")
+ @Option(names = {"-st", "--subscription-type"}, description =
"Subscription type")
public SubscriptionType subscriptionType = SubscriptionType.Shared;
- @Parameter(names = {"-rs", "--replicated" },
+ @Option(names = {"-rs", "--replicated" },
description = "Whether the subscription status should be
replicated")
private boolean replicatedSubscription = false;
- @Parameter(names = {"-q", "--receiver-queue-size"}, description =
"Size of the receiver queue")
+ @Option(names = {"-q", "--receiver-queue-size"}, description = "Size
of the receiver queue")
public int receiverQueueSize = 1000;
- @Parameter(names = {"-tto", "--txn-timeout"}, description = "Set the
time value of transaction timeout,"
+ @Option(names = {"-tto", "--txn-timeout"}, description = "Set the time
value of transaction timeout,"
+ " and the time unit is second. (After --txn-enable setting
to true, --txn-timeout takes effect)")
public long transactionTimeout = 5;
- @Parameter(names = {"-ntxn",
+ @Option(names = {"-ntxn",
"--number-txn"}, description = "Set the number of transaction.
0 means keeping open."
+ "If transaction disabled, it means the number of tasks. The
task or transaction produces or "
+ "consumes a specified number of messages.")
public long numTransactions = 0;
- @Parameter(names = {"-nmp", "--numMessage-perTransaction-produce"},
+ @Option(names = {"-nmp", "--numMessage-perTransaction-produce"},
description = "Set the number of messages produced in a
transaction."
+ "If transaction disabled, it means the number of
messages produced in a task.")
public int numMessagesProducedPerTransaction = 1;
- @Parameter(names = {"-nmc", "--numMessage-perTransaction-consume"},
+ @Option(names = {"-nmc", "--numMessage-perTransaction-consume"},
description = "Set the number of messages consumed in a
transaction."
+ "If transaction disabled, it means the number of
messages consumed in a task.")
public int numMessagesReceivedPerTransaction = 1;
- @Parameter(names = {"--txn-disable"}, description = "Disable
transaction")
+ @Option(names = {"--txn-disable"}, description = "Disable transaction")
public boolean isDisableTransaction = false;
- @Parameter(names = {"-abort"}, description = "Abort the transaction.
(After --txn-disEnable "
+ @Option(names = {"-abort"}, description = "Abort the transaction.
(After --txn-disEnable "
+ "setting to false, -abort takes effect)")
public boolean isAbortTransaction = false;
- @Parameter(names = "-txnRate", description = "Set the rate of opened
transaction or task. 0 means no limit")
+ @Option(names = "-txnRate", description = "Set the rate of opened
transaction or task. 0 means no limit")
public int openTxnRate = 0;
@Override
diff --git
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterValidator.java
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterConvert.java
similarity index 68%
rename from
pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterValidator.java
rename to
pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterConvert.java
index 7e8fe2181cd..fc045eb8aaf 100644
---
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterValidator.java
+++
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PositiveNumberParameterConvert.java
@@ -18,15 +18,16 @@
*/
package org.apache.pulsar.testclient;
-import com.beust.jcommander.IParameterValidator;
-import com.beust.jcommander.ParameterException;
-
-public class PositiveNumberParameterValidator implements IParameterValidator {
+import picocli.CommandLine.ITypeConverter;
+import picocli.CommandLine.TypeConversionException;
+public class PositiveNumberParameterConvert implements ITypeConverter<Integer>
{
@Override
- public void validate(String name, String value) throws ParameterException {
- if (Integer.parseInt(value) <= 0) {
- throw new ParameterException("Parameter " + name + " should be > 0
(found " + value + ")");
+ public Integer convert(String value) {
+ int result = Integer.parseInt(value);
+ if (result <= 0) {
+ throw new TypeConversionException("Parameter should be > 0 (found
" + value + ")");
}
+ return result;
}
}
diff --git
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/GenerateDocumentionTest.java
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/GenerateDocumentionTest.java
index 936275bcd41..73d7751e333 100644
---
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/GenerateDocumentionTest.java
+++
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/GenerateDocumentionTest.java
@@ -18,7 +18,9 @@
*/
package org.apache.pulsar.testclient;
+import org.testng.Assert;
import org.testng.annotations.Test;
+import picocli.CommandLine;
public class GenerateDocumentionTest {
@@ -32,4 +34,39 @@ public class GenerateDocumentionTest {
String[] args = new String[]{"-n", "produce", "-n", "consume"};
CmdGenerateDocumentation.main(args);
}
+
+ private static final String DESC = "desc";
+ @Test
+ public void testGetCommandOptionDescription(){
+ Arguments arguments = new Arguments();
+ CommandLine commander = new CommandLine(arguments);
+ String desc =
CmdGenerateDocumentation.getCommandDescription(commander);
+ Assert.assertEquals(desc, DESC);
+
+ commander.getCommandSpec().options().forEach(option -> {
+ String desc1 =
CmdGenerateDocumentation.getOptionDescription(option);
+ Assert.assertEquals(desc1, DESC);
+ });
+
+ ArgumentsWithoutDesc argumentsWithoutDesc = new ArgumentsWithoutDesc();
+ commander = new CommandLine(argumentsWithoutDesc);
+ desc = CmdGenerateDocumentation.getCommandDescription(commander);
+ Assert.assertEquals(desc, "");
+
+ commander.getCommandSpec().options().forEach(option -> {
+ String desc1 =
CmdGenerateDocumentation.getOptionDescription(option);
+ Assert.assertEquals(desc1, "");
+ });
+ }
+
+ @CommandLine.Command(description = DESC)
+ static class Arguments {
+ @CommandLine.Option(names = {"-h", "--help"}, description = DESC, help
= true)
+ boolean help;
+ }
+ @CommandLine.Command()
+ static class ArgumentsWithoutDesc {
+ @CommandLine.Option(names = {"-h", "--help"}, help = true)
+ boolean help;
+ }
}
\ No newline at end of file