You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dg...@apache.org on 2019/01/23 12:46:05 UTC

[ignite] branch master updated: IGNITE-10998 add help for idle_verify --check-crc - Fixes #5876.

This is an automated email from the ASF dual-hosted git repository.

dgovorukhin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 15cefea  IGNITE-10998 add help for idle_verify --check-crc - Fixes #5876.
15cefea is described below

commit 15cefeabe19098f9b6ff40e99cdb8c784c336a82
Author: sergey antonov <an...@gmail.com>
AuthorDate: Wed Jan 23 15:45:43 2019 +0300

    IGNITE-10998 add help for idle_verify --check-crc - Fixes #5876.
    
    Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
---
 .../internal/commandline/CommandHandler.java       | 244 +++++++++++----------
 .../internal/commandline/argument/CommandArg.java  |  28 +++
 .../commandline/argument/CommandArgUtils.java      |  46 ++++
 .../cache/argument/DistributionCommandArg.java     |  47 ++++
 .../cache/argument/IdleVerifyCommandArg.java       |  59 +++++
 .../commandline/cache/argument/ListCommandArg.java |  56 +++++
 .../cache/argument/ValidateIndexesCommandArg.java  |  50 +++++
 .../internal/commandline/CommandArgFactory.java    |  63 ++++++
 .../commandline/CommandHandlerParsingTest.java     |  22 +-
 .../apache/ignite/util/GridCommandHandlerTest.java |  30 ++-
 10 files changed, 520 insertions(+), 125 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
index b84e2b9..c3bc15c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
@@ -56,8 +56,13 @@ import org.apache.ignite.internal.client.GridClientNode;
 import org.apache.ignite.internal.client.GridServerUnreachableException;
 import org.apache.ignite.internal.client.impl.connection.GridClientConnectionResetException;
 import org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory;
+import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
 import org.apache.ignite.internal.commandline.cache.CacheArguments;
 import org.apache.ignite.internal.commandline.cache.CacheCommand;
+import org.apache.ignite.internal.commandline.cache.argument.DistributionCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.ListCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg;
 import org.apache.ignite.internal.commandline.cache.distribution.CacheDistributionTask;
 import org.apache.ignite.internal.commandline.cache.distribution.CacheDistributionTaskArg;
 import org.apache.ignite.internal.commandline.cache.distribution.CacheDistributionTaskResult;
@@ -148,6 +153,18 @@ import static org.apache.ignite.internal.commandline.cache.CacheCommand.IDLE_VER
 import static org.apache.ignite.internal.commandline.cache.CacheCommand.LIST;
 import static org.apache.ignite.internal.commandline.cache.CacheCommand.RESET_LOST_PARTITIONS;
 import static org.apache.ignite.internal.commandline.cache.CacheCommand.VALIDATE_INDEXES;
+import static org.apache.ignite.internal.commandline.cache.argument.DistributionCommandArg.USER_ATTRIBUTES;
+import static org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg.CACHE_FILTER;
+import static org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg.CHECK_CRC;
+import static org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg.DUMP;
+import static org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg.EXCLUDE_CACHES;
+import static org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg.SKIP_ZEROS;
+import static org.apache.ignite.internal.commandline.cache.argument.ListCommandArg.CONFIG;
+import static org.apache.ignite.internal.commandline.cache.argument.ListCommandArg.GROUP;
+import static org.apache.ignite.internal.commandline.cache.argument.ListCommandArg.OUTPUT_FORMAT;
+import static org.apache.ignite.internal.commandline.cache.argument.ListCommandArg.SEQUENCE;
+import static org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg.CHECK_FIRST;
+import static org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg.CHECK_THROUGH;
 import static org.apache.ignite.internal.visor.baseline.VisorBaselineOperation.ADD;
 import static org.apache.ignite.internal.visor.baseline.VisorBaselineOperation.COLLECT;
 import static org.apache.ignite.internal.visor.baseline.VisorBaselineOperation.REMOVE;
@@ -192,24 +209,9 @@ public class CommandHandler {
     /** */
     private static final String CMD_PING_TIMEOUT = "--ping-timeout";
 
-    /** */
-    private static final String CMD_DUMP = "--dump";
-
-    /** */
-    private static final String CMD_SKIP_ZEROS = "--skip-zeros";
-
-    /** Command exclude caches. */
-    private static final String CMD_EXCLUDE_CACHES = "--exclude-caches";
-
-    /** Cache filter. */
-    private static final String CACHE_FILTER = "--cache-filter";
-
     /** One cache filter option should used message. */
     public static final String ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG = "Should use only one of option: " +
-        CMD_EXCLUDE_CACHES + ", " + CACHE_FILTER + " or pass caches explicitly";
-
-    /** */
-    private static final String CMD_USER_ATTRIBUTES = "--user-attributes";
+        EXCLUDE_CACHES + ", " + CACHE_FILTER + " or pass caches explicitly";
 
     // SSL configuration section
 
@@ -291,12 +293,6 @@ public class CommandHandler {
     /** */
     private static final String BASELINE_SET_VERSION = "version";
 
-    /** Parameter name for validate_indexes command. */
-    static final String VI_CHECK_FIRST = "--check-first";
-
-    /** Parameter name for validate_indexes command. */
-    static final String VI_CHECK_THROUGH = "--check-through";
-
     /** */
     static final String WAL_PRINT = "print";
 
@@ -363,15 +359,6 @@ public class CommandHandler {
     /** */
     private static final String TX_KILL = "--kill";
 
-    /** */
-    private static final String OUTPUT_FORMAT = "--output-format";
-
-    /** */
-    private static final String CONFIG = "--config";
-
-    /** */
-    private static final String IDLE_CHECK_CRC = "--check-crc";
-
     /** Utility name. */
     private static final String UTILITY_NAME = "control.sh";
 
@@ -411,9 +398,9 @@ public class CommandHandler {
     /**
      * Creates list of common utility options.
      *
-     * @return List of common utility options.
+     * @return Array of common utility options.
      */
-    private static List<String> getCommonOptions() {
+    private static String[] getCommonOptions() {
         List<String> list = new ArrayList<>(32);
 
         list.add(op(CMD_HOST, "HOST_OR_IP"));
@@ -433,7 +420,7 @@ public class CommandHandler {
         list.add(op(CMD_TRUSTSTORE, "TRUSTSTORE_PATH"));
         list.add(op(CMD_TRUSTSTORE_PASSWORD, "TRUSTSTORE_PASSWORD"));
 
-        return list;
+        return list.toArray(new String[0]);
     }
 
     /**
@@ -861,22 +848,22 @@ public class CommandHandler {
     private void printCacheHelp() {
         log(i("The '" + CACHE + " subcommand' is used to get information about and perform actions with caches. The command has the following syntax:"));
         nl();
-        log(i(UTILITY_NAME_WITH_COMMON_OPTIONS + " " + CACHE + "[subcommand] <subcommand_parameters>"));
+        log(i(UTILITY_NAME_WITH_COMMON_OPTIONS + " " + CACHE + " [subcommand] <subcommand_parameters>"));
         nl();
         log(i("The subcommands that take " + OP_NODE_ID + " as an argument ('" + LIST + "', '" + CONTENTION + "' and '" + VALIDATE_INDEXES + "') will be executed on the given node or on all server nodes if the option is not specified. Other commands will run on a random server node."));
         nl();
         nl();
         log(i("Subcommands:"));
 
-        usageCache(LIST, "regexPattern", op(or("groups", "seq")), OP_NODE_ID, op(CONFIG), op(OUTPUT_FORMAT, MULTI_LINE));
+        String CACHES = "cacheName1,...,cacheNameN";
+
+        usageCache(LIST, "regexPattern", op(or(GROUP, SEQUENCE)), OP_NODE_ID, op(CONFIG), op(OUTPUT_FORMAT, MULTI_LINE));
         usageCache(CONTENTION, "minQueueSize", OP_NODE_ID, op("maxPrint"));
-        usageCache(IDLE_VERIFY, op(CMD_DUMP), op(CMD_SKIP_ZEROS), op(or(CMD_EXCLUDE_CACHES + " cache1,...,cacheN",
-            op(CACHE_FILTER, or(CacheFilterEnum.ALL.toString(), CacheFilterEnum.SYSTEM.toString(),
-                CacheFilterEnum.PERSISTENT.toString(), CacheFilterEnum.NOT_PERSISTENT.toString())), "cache1,...," +
-                "cacheN")));
-        usageCache(VALIDATE_INDEXES, "[cache1,...,cacheN]", OP_NODE_ID, op(or(VI_CHECK_FIRST + " N", VI_CHECK_THROUGH + " K")));
-        usageCache(DISTRIBUTION, or(NODE_ID, NULL), "[cacheName1,...,cacheNameN]", op(CMD_USER_ATTRIBUTES, "attrName1,...,attrNameN"));
-        usageCache(RESET_LOST_PARTITIONS, "cacheName1,...,cacheNameN");
+        usageCache(IDLE_VERIFY, op(DUMP), op(SKIP_ZEROS), op(CHECK_CRC),
+            op(or(g(EXCLUDE_CACHES, CACHES), g(CACHE_FILTER, or(CacheFilterEnum.values())), CACHES)));
+        usageCache(VALIDATE_INDEXES, op(CACHES), OP_NODE_ID, op(or(CHECK_FIRST + " N", CHECK_THROUGH + " K")));
+        usageCache(DISTRIBUTION, or(NODE_ID, NULL), op(CACHES), op(USER_ATTRIBUTES, "attrName1,...,attrNameN"));
+        usageCache(RESET_LOST_PARTITIONS, CACHES);
         nl();
     }
 
@@ -1771,13 +1758,20 @@ public class CommandHandler {
         Map<String, String> map = U.newLinkedHashMap(16);
         switch (cmd) {
             case LIST:
-                map.put(CONFIG, "print a all configuration parameters for each cache.");
-                map.put(OUTPUT_FORMAT + " " + MULTI_LINE.text(), "print configuration parameters per line. This option has effect only when used with " + CONFIG + " and without [groups|seq].");
+                map.put(CONFIG.toString(), "print all configuration parameters for each cache.");
+                map.put(OUTPUT_FORMAT + " " + MULTI_LINE, "print configuration parameters per line. This option has effect only when used with " + CONFIG + " and without " + op(or(GROUP, SEQUENCE)) + ".");
+                map.put(GROUP.toString(), "print information about groups.");
+                map.put(SEQUENCE.toString(), "print information about sequences.");
 
                 break;
             case VALIDATE_INDEXES:
-                map.put(VI_CHECK_FIRST + " N", "validate only the first N keys");
-                map.put(VI_CHECK_THROUGH + " K", "validate every Kth key");
+                map.put(CHECK_FIRST + " N", "validate only the first N keys");
+                map.put(CHECK_THROUGH + " K", "validate every Kth key");
+
+                break;
+
+            case IDLE_VERIFY:
+                map.put(CHECK_CRC.toString(), "check the CRC-sum of pages stored on disk before verifying data consistency in partitions between primary and backup nodes.");
 
                 break;
         }
@@ -1838,6 +1832,16 @@ public class CommandHandler {
     }
 
     /**
+     * Join input parameters with space and wrap grouping braces {@code ()}.
+     *
+     * @param params Input parameter.
+     * @return Joined parameters wrapped grouped braces.
+     */
+    private static String g(Object... params) {
+        return j(new SB(), "(", " ", params).a(")").toString();
+    }
+
+    /**
      * Extract next argument.
      *
      * @param err Error message.
@@ -2146,33 +2150,51 @@ public class CommandHandler {
                 while (hasNextCacheArg() && idleVerifyArgsCnt-- > 0) {
                     String nextArg = nextArg("");
 
-                    if (CMD_DUMP.equals(nextArg))
-                        cacheArgs.dump(true);
-                    else if (CMD_EXCLUDE_CACHES.equals(nextArg)) {
-                        if (cacheArgs.caches() != null || cacheArgs.getCacheFilterEnum() != CacheFilterEnum.ALL)
-                            throw new IllegalArgumentException(ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG);
+                    IdleVerifyCommandArg arg = CommandArgUtils.of(nextArg, IdleVerifyCommandArg.class);
 
-                        parseExcludeCacheNames(nextArg("Specify caches, which will be excluded."),
-                            cacheArgs);
-                    }
-                    else if (CMD_SKIP_ZEROS.equals(nextArg))
-                        cacheArgs.skipZeros(true);
-                    else if (IDLE_CHECK_CRC.equals(nextArg))
-                        cacheArgs.idleCheckCrc(true);
-                    else if (CACHE_FILTER.equals(nextArg)) {
-                        if (cacheArgs.caches() != null || cacheArgs.excludeCaches() != null)
+                    if(arg == null) {
+                        if (cacheArgs.excludeCaches() != null || cacheArgs.getCacheFilterEnum() != CacheFilterEnum.ALL)
                             throw new IllegalArgumentException(ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG);
 
-                        String filter = nextArg("The cache filter should be specified. The following values can be " +
-                            "used: " + Arrays.toString(CacheFilterEnum.values()) + '.');
-
-                        cacheArgs.setCacheFilterEnum(CacheFilterEnum.valueOf(filter.toUpperCase()));
+                        parseCacheNames(nextArg, cacheArgs);
                     }
                     else {
-                        if (cacheArgs.excludeCaches() != null || cacheArgs.getCacheFilterEnum() != CacheFilterEnum.ALL)
-                            throw new IllegalArgumentException(ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG);
+                        switch (arg) {
+                            case DUMP:
+                                cacheArgs.dump(true);
 
-                        parseCacheNames(nextArg, cacheArgs);
+                                break;
+
+                            case SKIP_ZEROS:
+                                cacheArgs.skipZeros(true);
+
+                                break;
+
+                            case CHECK_CRC:
+                                cacheArgs.idleCheckCrc(true);
+
+                                break;
+
+                            case CACHE_FILTER:
+                                if (cacheArgs.caches() != null || cacheArgs.excludeCaches() != null)
+                                    throw new IllegalArgumentException(ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG);
+
+                                String filter = nextArg("The cache filter should be specified. The following " +
+                                    "values can be used: " + Arrays.toString(CacheFilterEnum.values()) + '.');
+
+                                cacheArgs.setCacheFilterEnum(CacheFilterEnum.valueOf(filter.toUpperCase()));
+
+                                break;
+
+                            case EXCLUDE_CACHES:
+                                if (cacheArgs.caches() != null || cacheArgs.getCacheFilterEnum() != CacheFilterEnum.ALL)
+                                    throw new IllegalArgumentException(ONE_CACHE_FILTER_OPT_SHOULD_USED_MSG);
+
+                                parseExcludeCacheNames(nextArg("Specify caches, which will be excluded."),
+                                    cacheArgs);
+
+                                break;
+                        }
                     }
                 }
                 break;
@@ -2194,11 +2216,13 @@ public class CommandHandler {
                 int argsCnt = 0;
 
                 while (hasNextCacheArg() && argsCnt++ < 4) {
-                    String arg = nextArg("");
+                    String nextArg = nextArg("");
+
+                    ValidateIndexesCommandArg arg = CommandArgUtils.of(nextArg, ValidateIndexesCommandArg.class);
 
-                    if (VI_CHECK_FIRST.equals(arg) || VI_CHECK_THROUGH.equals(arg)) {
+                    if(arg == CHECK_FIRST || arg == CHECK_THROUGH) {
                         if (!hasNextCacheArg())
-                            throw new IllegalArgumentException("Numeric value for '" + arg + "' parameter expected.");
+                            throw new IllegalArgumentException("Numeric value for '" + nextArg + "' parameter expected.");
 
                         int numVal;
 
@@ -2209,17 +2233,14 @@ public class CommandHandler {
                         }
                         catch (IllegalArgumentException e) {
                             throw new IllegalArgumentException(
-                                "Not numeric value was passed for '"
-                                    + arg
-                                    + "' parameter: "
-                                    + numStr
+                                "Not numeric value was passed for '" + nextArg + "' parameter: " + numStr
                             );
                         }
 
                         if (numVal <= 0)
-                            throw new IllegalArgumentException("Value for '" + arg + "' property should be positive.");
+                            throw new IllegalArgumentException("Value for '" + nextArg + "' property should be positive.");
 
-                        if (VI_CHECK_FIRST.equals(arg))
+                        if (arg == CHECK_FIRST)
                             cacheArgs.checkFirst(numVal);
                         else
                             cacheArgs.checkThrough(numVal);
@@ -2228,7 +2249,7 @@ public class CommandHandler {
                     }
 
                     try {
-                        cacheArgs.nodeId(UUID.fromString(arg));
+                        cacheArgs.nodeId(UUID.fromString(nextArg));
 
                         continue;
                     }
@@ -2236,7 +2257,7 @@ public class CommandHandler {
                         //No-op.
                     }
 
-                    parseCacheNames(arg, cacheArgs);
+                    parseCacheNames(nextArg, cacheArgs);
                 }
 
                 break;
@@ -2249,7 +2270,9 @@ public class CommandHandler {
                 while (hasNextCacheArg()) {
                     String nextArg = nextArg("");
 
-                    if (CMD_USER_ATTRIBUTES.equals(nextArg)) {
+                    DistributionCommandArg arg = CommandArgUtils.of(nextArg, DistributionCommandArg.class);
+
+                    if (arg == USER_ATTRIBUTES) {
                         nextArg = nextArg("User attributes are expected to be separated by commas");
 
                         Set<String> userAttrs = new HashSet<>();
@@ -2282,34 +2305,36 @@ public class CommandHandler {
                 OutputFormat outputFormat = SINGLE_LINE;
 
                 while (hasNextCacheArg()) {
-                    String tmp = nextArg("").toLowerCase();
+                    String nextArg = nextArg("").toLowerCase();
 
-                    switch (tmp) {
-                        case "groups":
-                            cacheCmd = GROUPS;
+                    ListCommandArg arg = CommandArgUtils.of(nextArg, ListCommandArg.class);
+                    if (arg != null) {
+                        switch (arg) {
+                            case GROUP:
+                                cacheCmd = GROUPS;
 
-                            break;
+                                break;
 
-                        case "seq":
-                            cacheCmd = SEQ;
+                            case SEQUENCE:
+                                cacheCmd = SEQ;
 
-                            break;
-
-                        case OUTPUT_FORMAT:
-                            String tmp2 = nextArg("output format must be defined!").toLowerCase();
+                                break;
 
-                            outputFormat = OutputFormat.fromConsoleName(tmp2);
+                            case OUTPUT_FORMAT:
+                                String tmp2 = nextArg("output format must be defined!").toLowerCase();
 
-                            break;
+                                outputFormat = OutputFormat.fromConsoleName(tmp2);
 
-                        case CONFIG:
-                            cacheArgs.fullConfig(true);
+                                break;
 
-                            break;
+                            case CONFIG:
+                                cacheArgs.fullConfig(true);
 
-                        default:
-                            cacheArgs.nodeId(UUID.fromString(tmp));
+                                break;
+                        }
                     }
+                    else
+                        cacheArgs.nodeId(UUID.fromString(nextArg));
                 }
 
                 cacheArgs.cacheCommand(cacheCmd);
@@ -2335,20 +2360,11 @@ public class CommandHandler {
     }
 
     /**
+     * @param cacheNames Cache names string.
      * @param cacheArgs Cache args.
      */
     private void parseCacheNames(String cacheNames, CacheArguments cacheArgs) {
-        String[] cacheNamesArr = cacheNames.split(",");
-        Set<String> cacheNamesSet = new HashSet<>();
-
-        for (String cacheName : cacheNamesArr) {
-            if (F.isEmpty(cacheName))
-                throw new IllegalArgumentException("Non-empty cache names expected.");
-
-            cacheNamesSet.add(cacheName.trim());
-        }
-
-        cacheArgs.caches(cacheNamesSet);
+        cacheArgs.caches(parseCacheNames(cacheNames));
     }
 
     /**
@@ -2356,7 +2372,15 @@ public class CommandHandler {
      * @param cacheArgs Cache args.
      */
     private void parseExcludeCacheNames(String cacheNames, CacheArguments cacheArgs) {
+        cacheArgs.excludeCaches(parseCacheNames(cacheNames));
+    }
+
+    /**
+     * @param cacheNames Cache names string.
+     */
+    private Set<String> parseCacheNames(String cacheNames) {
         String[] cacheNamesArr = cacheNames.split(",");
+
         Set<String> cacheNamesSet = new HashSet<>();
 
         for (String cacheName : cacheNamesArr) {
@@ -2366,7 +2390,7 @@ public class CommandHandler {
             cacheNamesSet.add(cacheName.trim());
         }
 
-        cacheArgs.excludeCaches(cacheNamesSet);
+        return cacheNamesSet;
     }
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArg.java
new file mode 100644
index 0000000..0665dda
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArg.java
@@ -0,0 +1,28 @@
+/*
+ *  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.ignite.internal.commandline.argument;
+
+/**
+ * Command argument interface.
+ */
+public interface CommandArg {
+    /**
+     * @return Argument name.
+     */
+    String argName();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArgUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArgUtils.java
new file mode 100644
index 0000000..6cd16f1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/argument/CommandArgUtils.java
@@ -0,0 +1,46 @@
+/*
+ *  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.ignite.internal.commandline.argument;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Utility class for control.sh arguments.
+ */
+public class CommandArgUtils {
+    /**
+     * Tries convert {@code text} to one of values {@code enumClass}.
+     * @param text Input test.
+     * @param enumClass {@link CommandArg} enum class.
+     * @param <E>
+     * @return Converted argument or {@code null} if convert failed.
+     */
+    public static <E extends Enum<E> & CommandArg> @Nullable E of(String text, Class<E> enumClass) {
+        for (E e : enumClass.getEnumConstants()) {
+            if (e.argName().equalsIgnoreCase(text))
+                return e;
+        }
+
+        return null;
+    }
+
+    /** Private constructor. */
+    private CommandArgUtils() {
+        /* No-op. */
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/DistributionCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/DistributionCommandArg.java
new file mode 100644
index 0000000..129f7a8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/DistributionCommandArg.java
@@ -0,0 +1,47 @@
+/*
+ *  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.ignite.internal.commandline.cache.argument;
+
+import org.apache.ignite.internal.commandline.argument.CommandArg;
+import org.apache.ignite.internal.commandline.cache.CacheCommand;
+
+/**
+ * {@link CacheCommand#DISTRIBUTION} command arguments.
+ */
+public enum DistributionCommandArg implements CommandArg {
+    /** User attributes. */
+    USER_ATTRIBUTES("--user-attributes");
+
+    /** Option name. */
+    private final String name;
+
+    /** */
+    DistributionCommandArg(String name) {
+        this.name = name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String argName() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/IdleVerifyCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/IdleVerifyCommandArg.java
new file mode 100644
index 0000000..c435ed8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/IdleVerifyCommandArg.java
@@ -0,0 +1,59 @@
+/*
+ *  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.ignite.internal.commandline.cache.argument;
+
+import org.apache.ignite.internal.commandline.argument.CommandArg;
+import org.apache.ignite.internal.commandline.cache.CacheCommand;
+
+/**
+ * {@link CacheCommand#IDLE_VERIFY} command arguments.
+ */
+public enum IdleVerifyCommandArg implements CommandArg {
+    /** Dump. */
+    DUMP("--dump"),
+
+    /** Skip zeros. */
+    SKIP_ZEROS("--skip-zeros"),
+
+    /** Exclude caches. */
+    EXCLUDE_CACHES("--exclude-caches"),
+
+    /** Check crc. */
+    CHECK_CRC("--check-crc"),
+
+    /** Cache filter. */
+    CACHE_FILTER("--cache-filter");
+
+    /** Option name. */
+    private final String name;
+
+    /** */
+    IdleVerifyCommandArg(String name) {
+        this.name = name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String argName() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ListCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ListCommandArg.java
new file mode 100644
index 0000000..be8166b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ListCommandArg.java
@@ -0,0 +1,56 @@
+/*
+ *  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.ignite.internal.commandline.cache.argument;
+
+import org.apache.ignite.internal.commandline.argument.CommandArg;
+import org.apache.ignite.internal.commandline.cache.CacheCommand;
+
+/**
+ * {@link CacheCommand#LIST} command arguments.
+ */
+public enum ListCommandArg implements CommandArg {
+    /** Group. */
+    GROUP("--groups"),
+
+    /** Sequence. */
+    SEQUENCE("--seq"),
+
+    /** Output format. */
+    OUTPUT_FORMAT("--output-format"),
+
+    /** Config. */
+    CONFIG("--config");
+
+    /** Option name. */
+    private final String name;
+
+    /** */
+    ListCommandArg(String name) {
+        this.name = name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String argName() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ValidateIndexesCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ValidateIndexesCommandArg.java
new file mode 100644
index 0000000..057d4d5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/argument/ValidateIndexesCommandArg.java
@@ -0,0 +1,50 @@
+/*
+ *  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.ignite.internal.commandline.cache.argument;
+
+import org.apache.ignite.internal.commandline.argument.CommandArg;
+import org.apache.ignite.internal.commandline.cache.CacheCommand;
+
+/**
+ * {@link CacheCommand#VALIDATE_INDEXES} command arguments.
+ */
+public enum ValidateIndexesCommandArg implements CommandArg {
+    /** Check first. */
+    CHECK_FIRST("--check-first"),
+
+    /** Check through. */
+    CHECK_THROUGH("--check-through");
+
+    /** Option name. */
+    private final String name;
+
+    /** */
+    ValidateIndexesCommandArg(String name) {
+        this.name = name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String argName() {
+        return name;
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandArgFactory.java b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandArgFactory.java
new file mode 100644
index 0000000..9a5b791
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandArgFactory.java
@@ -0,0 +1,63 @@
+/*
+ *  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.ignite.internal.commandline;
+
+import java.util.Collections;
+import org.apache.ignite.internal.commandline.argument.CommandArg;
+import org.apache.ignite.internal.commandline.cache.CacheCommand;
+import org.apache.ignite.internal.commandline.cache.argument.DistributionCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.ListCommandArg;
+import org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg;
+
+/**
+ * Command arguments factory used for tests.
+ */
+public class CommandArgFactory {
+    /**
+     * @param cmd Cache command.
+     * @return Possible arguments for passed cache command {@code cmd} or empty array, if arguments not defined for
+     * cache command.
+     */
+    public static CommandArg[] getArgs(CacheCommand cmd) {
+        switch (cmd) {
+            case RESET_LOST_PARTITIONS:
+            case CONTENTION:
+            case HELP:
+                return new CommandArg[0];
+
+            case DISTRIBUTION:
+                return DistributionCommandArg.values();
+            case IDLE_VERIFY:
+                return IdleVerifyCommandArg.values();
+
+            case LIST:
+                return ListCommandArg.values();
+
+            case VALIDATE_INDEXES:
+                return ValidateIndexesCommandArg.values();
+        }
+
+        throw new IllegalArgumentException("Unknown cache command " + cmd);
+    }
+
+    /** Private constructor */
+    private CommandArgFactory() {
+        /* No-op. */
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
index 7c942b2..f261292 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
@@ -21,7 +21,6 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.UUID;
 import org.apache.ignite.internal.commandline.cache.CacheArguments;
-import org.apache.ignite.internal.commandline.cache.CacheCommand;
 import org.apache.ignite.internal.visor.tx.VisorTxOperation;
 import org.apache.ignite.internal.visor.tx.VisorTxProjection;
 import org.apache.ignite.internal.visor.tx.VisorTxSortOrder;
@@ -36,10 +35,11 @@ import static org.apache.ignite.internal.commandline.Command.CACHE;
 import static org.apache.ignite.internal.commandline.Command.WAL;
 import static org.apache.ignite.internal.commandline.CommandHandler.DFLT_HOST;
 import static org.apache.ignite.internal.commandline.CommandHandler.DFLT_PORT;
-import static org.apache.ignite.internal.commandline.CommandHandler.VI_CHECK_FIRST;
-import static org.apache.ignite.internal.commandline.CommandHandler.VI_CHECK_THROUGH;
 import static org.apache.ignite.internal.commandline.CommandHandler.WAL_DELETE;
 import static org.apache.ignite.internal.commandline.CommandHandler.WAL_PRINT;
+import static org.apache.ignite.internal.commandline.cache.CacheCommand.VALIDATE_INDEXES;
+import static org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg.CHECK_FIRST;
+import static org.apache.ignite.internal.commandline.cache.argument.ValidateIndexesCommandArg.CHECK_THROUGH;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
@@ -78,12 +78,12 @@ public class CommandHandlerParsingTest {
             CacheArguments args = hnd.parseAndValidate(
                 Arrays.asList(
                     CACHE.text(),
-                    CacheCommand.VALIDATE_INDEXES.text(),
+                    VALIDATE_INDEXES.text(),
                     "cache1, cache2",
                     nodeId.toString(),
-                    VI_CHECK_FIRST,
+                    CHECK_FIRST.toString(),
                     Integer.toString(expectedCheckFirst),
-                    VI_CHECK_THROUGH,
+                    CHECK_THROUGH.toString(),
                     Integer.toString(expectedCheckThrough)
                 )
             ).cacheArgs();
@@ -103,9 +103,9 @@ public class CommandHandlerParsingTest {
             CacheArguments args = hnd.parseAndValidate(
                 Arrays.asList(
                     CACHE.text(),
-                    CacheCommand.VALIDATE_INDEXES.text(),
+                    VALIDATE_INDEXES.text(),
                     nodeId.toString(),
-                    VI_CHECK_THROUGH,
+                    CHECK_THROUGH.toString(),
                     Integer.toString(expectedParam)
                 )
             ).cacheArgs();
@@ -123,8 +123,8 @@ public class CommandHandlerParsingTest {
             hnd.parseAndValidate(
                 Arrays.asList(
                     CACHE.text(),
-                    CacheCommand.VALIDATE_INDEXES.text(),
-                    VI_CHECK_FIRST,
+                    VALIDATE_INDEXES.text(),
+                    CHECK_FIRST.toString(),
                     "0"
                 )
             );
@@ -136,7 +136,7 @@ public class CommandHandlerParsingTest {
         }
 
         try {
-            hnd.parseAndValidate(Arrays.asList(CACHE.text(), CacheCommand.VALIDATE_INDEXES.text(), VI_CHECK_THROUGH));
+            hnd.parseAndValidate(Arrays.asList(CACHE.text(), VALIDATE_INDEXES.text(), CHECK_THROUGH.toString()));
 
             fail("Expected exception hasn't been thrown");
         }
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 29d40d2..e4357aa 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -66,7 +66,9 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.TestRecordingCommunicationSpi;
 import org.apache.ignite.internal.commandline.Command;
+import org.apache.ignite.internal.commandline.CommandArgFactory;
 import org.apache.ignite.internal.commandline.CommandHandler;
+import org.apache.ignite.internal.commandline.argument.CommandArg;
 import org.apache.ignite.internal.commandline.cache.CacheCommand;
 import org.apache.ignite.internal.managers.communication.GridIoMessage;
 import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
@@ -945,9 +947,29 @@ public class GridCommandHandlerTest extends GridCommonAbstractTest {
 
         assertEquals(EXIT_CODE_OK, execute("--cache", "help"));
 
+        String output = testOut.toString();
+
         for (CacheCommand cmd : CacheCommand.values()) {
-            if (cmd != HELP)
-                assertTrue(cmd.text(), testOut.toString().contains(cmd.toString()));
+            if (cmd != HELP) {
+                assertTrue(cmd.text(), output.contains(cmd.toString()));
+
+                for (CommandArg arg : CommandArgFactory.getArgs(cmd))
+                    assertTrue(cmd + " " + arg, output.contains(arg.toString()));
+
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCorrectCacheOptionsNaming() throws Exception {
+        Pattern p = Pattern.compile("^--([a-z]+(-)?)+([a-z]+)");
+
+        for(CacheCommand cmd : CacheCommand.values()) {
+            for (CommandArg arg : CommandArgFactory.getArgs(cmd))
+                assertTrue(arg.toString(), p.matcher(arg.toString()).matches());
         }
     }
 
@@ -1699,7 +1721,7 @@ public class GridCommandHandlerTest extends GridCommonAbstractTest {
 
         injectTestSystemOut();
 
-        assertEquals(EXIT_CODE_OK, execute("--cache", "list", "testSeq.*", "seq"));
+        assertEquals(EXIT_CODE_OK, execute("--cache", "list", "testSeq.*", "--seq"));
 
         assertTrue(testOut.toString().contains("testSeq"));
         assertTrue(testOut.toString().contains("testSeq2"));
@@ -1725,7 +1747,7 @@ public class GridCommandHandlerTest extends GridCommonAbstractTest {
 
         injectTestSystemOut();
 
-        assertEquals(EXIT_CODE_OK, execute("--cache", "list", ".*", "groups"));
+        assertEquals(EXIT_CODE_OK, execute("--cache", "list", ".*", "--groups"));
 
         assertTrue(testOut.toString().contains("G100"));
     }