This is an automated email from the ASF dual-hosted git repository. namelchev 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 32f7a7ea531 IGNITE-20592 Added the multiple nodes argument to the 'schedule_indexes_rebuild' command (#10982) 32f7a7ea531 is described below commit 32f7a7ea53126afd2db830f767ebe16b87f49d0b Author: Vladimir Steshin <vlads...@gmail.com> AuthorDate: Thu Oct 19 16:24:38 2023 +0300 IGNITE-20592 Added the multiple nodes argument to the 'schedule_indexes_rebuild' command (#10982) --- docs/_docs/tools/control-script.adoc | 2 +- .../commandline/CommandHandlerParsingTest.java | 77 ++++++++ .../GridCommandHandlerIndexForceRebuildTest.java | 37 +--- ...GridCommandHandlerScheduleIndexRebuildTest.java | 216 ++++++++++++++++----- .../internal/management/api/CommandUtils.java | 2 +- .../cache/CacheIndexesForceRebuildCommand.java | 31 +-- .../cache/CacheIndexesForceRebuildCommandArg.java | 3 +- .../cache/CacheScheduleIndexesRebuildCommand.java | 132 +++++++++++-- .../CacheScheduleIndexesRebuildCommandArg.java | 42 +++- ...mandHandlerClusterByClassTest_cache_help.output | 8 +- ...dlerClusterByClassWithSSLTest_cache_help.output | 8 +- 11 files changed, 443 insertions(+), 115 deletions(-) diff --git a/docs/_docs/tools/control-script.adoc b/docs/_docs/tools/control-script.adoc index 843878b6a5f..808cbdff438 100644 --- a/docs/_docs/tools/control-script.adoc +++ b/docs/_docs/tools/control-script.adoc @@ -1278,7 +1278,7 @@ The `schedule_indexes_rebuild` commands Apache Ignite to rebuild indexes for spe [source, shell] ---- - control.sh|bat --cache schedule_indexes_rebuild --node-id nodeId --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN + control.sh|bat --cache schedule_indexes_rebuild --node-ids nodeId1,...nodeIdN|--all-nodes --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN ---- Parameters: diff --git a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java index d150f9e75ab..bbb68b62e93 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java @@ -980,6 +980,52 @@ public class CommandHandlerParsingTest { IllegalArgumentException.class, "Unexpected value: --some-other-arg" ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList( + CACHE, "indexes_force_rebuild", + "--node-id", nodeId, + "--node-ids", nodeId + ',' + nodeId, + "--cache-names", "someNames" + )), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id] allowed" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList( + CACHE, "indexes_force_rebuild", + "--node-id", nodeId, + "--all-nodes" + )), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id] allowed" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList( + CACHE, "indexes_force_rebuild", + "--node-ids", nodeId + ',' + nodeId, + "--all-nodes" + )), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id] allowed" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList( + CACHE, "indexes_force_rebuild", + "--node-id", nodeId, + "--node-ids", nodeId + ',' + nodeId, + "--all-nodes" + )), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id] allowed" + ); } /** */ @@ -1037,6 +1083,37 @@ public class CommandHandlerParsingTest { IllegalArgumentException.class, "Square brackets must contain comma-separated indexes or not be used at all." ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList(CACHE, "schedule_indexes_rebuild", "--node-id", nodeId, "--all-nodes", "--group-names", "a")), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id]" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList(CACHE, "schedule_indexes_rebuild", "--node-id", nodeId, "--node-ids", nodeId + ',' + nodeId, + "--group-names", "a")), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id]" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList(CACHE, "schedule_indexes_rebuild", "--all-nodes", "--node-ids", nodeId + ',' + nodeId, + "--group-names", "a")), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id]" + ); + + GridTestUtils.assertThrows( + null, + () -> parseArgs(asList(CACHE, "schedule_indexes_rebuild", "--node-id", nodeId, "--all-nodes", + "--node-ids", nodeId + ',' + nodeId, "--group-names", "a")), + IllegalArgumentException.class, + "Only one of [--node-ids, --all-nodes, --node-id]" + ); } /** */ diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerIndexForceRebuildTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerIndexForceRebuildTest.java index 806794d73f1..ee269d7c4e7 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerIndexForceRebuildTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerIndexForceRebuildTest.java @@ -285,37 +285,6 @@ public class GridCommandHandlerIndexForceRebuildTest extends GridCommandHandlerA removeLogListener(grid(LAST_NODE_NUM), lsnr); } - /** - * Checks two arguments in the group are not allowed. - */ - @Test - public void testInvalidArgumentGroups() { - injectTestSystemOut(); - - assertContains(log, executeCommand(EXIT_CODE_INVALID_ARGUMENTS, "--cache", "indexes_force_rebuild", - "--node-ids", grid(LAST_NODE_NUM).localNode().id().toString() + ',' + grid(0).localNode().id().toString(), - "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), - "--cache-names", CACHE_NAME_NO_GRP), - "Only one of [--node-ids, --all-nodes, --node-id] allowed"); - - assertContains(log, executeCommand(EXIT_CODE_INVALID_ARGUMENTS, "--cache", "indexes_force_rebuild", - "--node-ids", grid(LAST_NODE_NUM).localNode().id().toString() + ',' + grid(0).localNode().id().toString(), - "--all-nodes", - "--cache-names", CACHE_NAME_NO_GRP), - "Only one of [--node-ids, --all-nodes, --node-id] allowed"); - - assertContains(log, executeCommand(EXIT_CODE_INVALID_ARGUMENTS, "--cache", "indexes_force_rebuild", - "--all-nodes", - "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), - "--cache-names", CACHE_NAME_NO_GRP), - "Only one of [--node-ids, --all-nodes, --node-id] allowed"); - - assertContains(log, executeCommand(EXIT_CODE_INVALID_ARGUMENTS, "--cache", "indexes_force_rebuild", - "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), - "--cache-names", CACHE_NAME_NO_GRP, "--group-names", CACHE_NAME_NO_GRP), - "Only one of [--group-names, --cache-names] allowed"); - } - /** * Checks --node-id and --cache-names options, * correctness of utility output and the fact that indexes were actually rebuilt. @@ -730,7 +699,7 @@ public class GridCommandHandlerIndexForceRebuildTest extends GridCommandHandlerA assertContains( log, outputStr, - "WARNING: These caches were not found:" + U.nl() + makeStringListWithIndent(cacheNames) + CacheIndexesForceRebuildCommand.PREF_CACHES_NOT_FOUND + U.nl() + makeStringListWithIndent(cacheNames) ); } @@ -744,7 +713,7 @@ public class GridCommandHandlerIndexForceRebuildTest extends GridCommandHandlerA assertContains( log, outputStr, - "WARNING: These cache groups were not found:" + U.nl() + makeStringListWithIndent(cacheGrps) + CacheIndexesForceRebuildCommand.PREF_GROUPS_NOT_FOUND + U.nl() + makeStringListWithIndent(cacheGrps) ); } @@ -815,7 +784,7 @@ public class GridCommandHandlerIndexForceRebuildTest extends GridCommandHandlerA * @param prefix Prefix or header to search. * @param targetStr Target string to search after {@code prefix}. */ - private static void validateMultiNodeOutput(String outputStr, String prefix, String targetStr) { + static void validateMultiNodeOutput(String outputStr, String prefix, String targetStr) { String[] lines = outputStr.split(U.nl()); for (int i = 0, heraderIdx = -1; i < lines.length; ++i) { diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerScheduleIndexRebuildTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerScheduleIndexRebuildTest.java index 8275a5b4bc5..92bd213836c 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerScheduleIndexRebuildTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerScheduleIndexRebuildTest.java @@ -19,6 +19,7 @@ package org.apache.ignite.util; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -26,17 +27,21 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.apache.ignite.Ignite; import org.apache.ignite.cluster.ClusterState; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.cache.query.index.Index; import org.apache.ignite.internal.cache.query.index.sorted.maintenance.MaintenanceRebuildIndexTarget; +import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.G; import org.apache.ignite.internal.util.typedef.internal.CU; import org.apache.ignite.maintenance.MaintenanceTask; import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.ListeningTestLogger; +import org.jetbrains.annotations.Nullable; import org.junit.Test; import static java.util.Collections.singletonMap; @@ -46,8 +51,15 @@ import static java.util.stream.Collectors.toSet; import static org.apache.ignite.internal.cache.query.index.sorted.maintenance.MaintenanceRebuildIndexUtils.parseMaintenanceTaskParameters; import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK; import static org.apache.ignite.internal.management.api.CommandUtils.INDENT; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_CACHES_NOT_FOUND; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_GROUPS_NOT_FOUND; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_SCHEDULED; +import static org.apache.ignite.internal.management.cache.CacheScheduleIndexesRebuildCommand.PREF_INDEXES_NOT_FOUND; +import static org.apache.ignite.internal.management.cache.CacheScheduleIndexesRebuildCommand.PREF_REBUILD_NOT_SCHEDULED; +import static org.apache.ignite.internal.management.cache.CacheScheduleIndexesRebuildCommand.PREF_REBUILD_NOT_SCHEDULED_MULTI; import static org.apache.ignite.internal.util.IgniteUtils.max; import static org.apache.ignite.testframework.GridTestUtils.assertContains; +import static org.apache.ignite.util.GridCommandHandlerIndexForceRebuildTest.validateMultiNodeOutput; import static org.apache.ignite.util.GridCommandHandlerIndexingUtils.breakSqlIndex; import static org.apache.ignite.util.GridCommandHandlerIndexingUtils.complexIndexEntity; import static org.apache.ignite.util.GridCommandHandlerIndexingUtils.createAndFillCache; @@ -153,57 +165,102 @@ public class GridCommandHandlerScheduleIndexRebuildTest extends GridCommandHandl } /** - * Checks error messages when trying to rebuild indexes for non-existent cache, when trying - * to rebuild non-existent indexes or when not specifying any indexes inside the square brackets. + * Checks error messages on single node. */ @Test public void testErrors() { - injectTestSystemOut(); + doTestErrors(false); + } - IgniteEx lastNode = grid(LAST_NODE_NUM); + /** + * Checks error messages on all nodes. + */ + @Test + public void testErrorsAllNodes() { + doTestErrors(true); + } + + /** + * Checks error messages when trying to rebuild indexes for non-existent cache, when trying + * to rebuild non-existent indexes or when not specifying any indexes inside the square brackets. + * + * @param allNodes If {@code True}, runs on all nodes using '--all-nodes'. + */ + private void doTestErrors(boolean allNodes) { + injectTestSystemOut(); // Tests non-existing cache name. - assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", - "--node-id", lastNode.localNode().id().toString(), - "--cache-names", CACHE_NAME_NON_EXISTING)); + if (allNodes) { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--all-nodes", "--cache-names", CACHE_NAME_NON_EXISTING)); + } + else { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), "--cache-names", CACHE_NAME_NON_EXISTING)); + } String notExistingCacheOutputStr = testOut.toString(); - assertTrue(notExistingCacheOutputStr.contains("WARNING: Indexes rebuild was not scheduled for any cache. Check command input.")); + assertTrue(notExistingCacheOutputStr.contains(allNodes ? PREF_REBUILD_NOT_SCHEDULED_MULTI : PREF_REBUILD_NOT_SCHEDULED)); assertTrue(notExistingCacheOutputStr.contains( - "WARNING: These caches were not found:" + System.lineSeparator() - + INDENT + CACHE_NAME_NON_EXISTING + PREF_CACHES_NOT_FOUND + System.lineSeparator() + + INDENT + CACHE_NAME_NON_EXISTING )); // Test non-existing cache group name. - assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", - "--node-id", lastNode.localNode().id().toString(), - "--group-names", GROUP_NAME_NON_EXISTING)); + if (allNodes) { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--all-nodes", "--group-names", GROUP_NAME_NON_EXISTING)); + } + else { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), + "--group-names", GROUP_NAME_NON_EXISTING)); + } String notExistingGroupOutputStr = testOut.toString(); - assertTrue(notExistingGroupOutputStr.contains("WARNING: Indexes rebuild was not scheduled for any cache. Check command input.")); + assertTrue(notExistingGroupOutputStr.contains(allNodes ? PREF_REBUILD_NOT_SCHEDULED_MULTI : PREF_REBUILD_NOT_SCHEDULED)); assertTrue(notExistingGroupOutputStr.contains( - "WARNING: These cache groups were not found:" + System.lineSeparator() - + INDENT + GROUP_NAME_NON_EXISTING + PREF_GROUPS_NOT_FOUND + System.lineSeparator() + + INDENT + GROUP_NAME_NON_EXISTING )); testOut.reset(); // Tests non-existing index name. - assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", - "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), - "--cache-names", CACHE_NAME_1_1 + "[non-existing-index]")); + if (allNodes) { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--all-nodes", "--cache-names", CACHE_NAME_1_1 + "[non-existing-index]")); + } + else { + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + "--node-id", grid(LAST_NODE_NUM).localNode().id().toString(), + "--cache-names", CACHE_NAME_1_1 + "[non-existing-index]")); + } String notExistingIndexOutputStr = testOut.toString(); - assertTrue(notExistingIndexOutputStr.contains("WARNING: Indexes rebuild was not scheduled for any cache. Check command input.")); + if (allNodes) { + for (Ignite ig : G.allGrids()) { + validateMultiNodeOutput(notExistingIndexOutputStr, PREF_REBUILD_NOT_SCHEDULED_MULTI, + ig.cluster().localNode().id().toString()); + + validateMultiNodeOutput(notExistingIndexOutputStr, PREF_INDEXES_NOT_FOUND, + ig.cluster().localNode().id().toString()); + } - assertTrue(notExistingIndexOutputStr.contains( - "WARNING: These indexes were not found:" + System.lineSeparator() - + INDENT + CACHE_NAME_1_1 + ":" + System.lineSeparator() - + INDENT + INDENT + "non-existing-index") - ); + validateMultiNodeOutput(notExistingIndexOutputStr, PREF_INDEXES_NOT_FOUND, "non-existing-index"); + } + else { + assertTrue(notExistingIndexOutputStr.contains(PREF_REBUILD_NOT_SCHEDULED)); + + assertTrue(notExistingIndexOutputStr.contains( + PREF_INDEXES_NOT_FOUND + System.lineSeparator() + + INDENT + CACHE_NAME_1_1 + ":" + System.lineSeparator() + + INDENT + INDENT + "non-existing-index") + ); + } } /** @@ -211,29 +268,75 @@ public class GridCommandHandlerScheduleIndexRebuildTest extends GridCommandHandl */ @Test public void testRebuild() throws Exception { - IgniteEx node = grid(LAST_NODE_NUM); + doTestRebuildOnSpecifiedNodes(Collections.singletonList(LAST_NODE_NUM)); + } - assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", - "--node-id", node.localNode().id().toString(), - "--cache-names", CACHE_NAME_NO_GRP)); + /** + * Checks that index is rebuilt correctly using --node-ids. + */ + @Test + public void testRebuildOnSpecifiedNodes() throws Exception { + doTestRebuildOnSpecifiedNodes(Arrays.asList(0, 1, LAST_NODE_NUM)); + } - checkIndexesRebuildScheduled(node, singletonMap(CU.cacheId(CACHE_NAME_NO_GRP), indexes(node, CACHE_NAME_NO_GRP))); + /** + * Checks that index is rebuilt correctly using --all-nodes. + */ + @Test + public void testRebuildOnAllNodes() throws Exception { + doTestRebuildOnSpecifiedNodes(Collections.emptyList()); + } - node.close(); + /** */ + private void doTestRebuildOnSpecifiedNodes(Collection<Integer> gridIdxs) throws Exception { + Collection<IgniteEx> grids = gridIdxs.stream().map(this::grid).collect(Collectors.toList()); - node = startGrid(LAST_NODE_NUM); + if (gridIdxs.isEmpty()) { + injectTestSystemOut(); - assertTrue(node.context().maintenanceRegistry().isMaintenanceMode()); + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", "--all-nodes", + "--cache-names", CACHE_NAME_NO_GRP)); - assertTrue(waitForIndexesRebuild(grid(LAST_NODE_NUM))); + String notExistingCacheOutputStr = testOut.toString(); - node.close(); + assertTrue(notExistingCacheOutputStr.contains(PREF_SCHEDULED)); + assertTrue(notExistingCacheOutputStr.contains("of cache '" + CACHE_NAME_NO_GRP + "'")); - node = startGrid(LAST_NODE_NUM); + for (Ignite ig : grids) + assertTrue(notExistingCacheOutputStr.contains(ig.cluster().localNode().id().toString())); - assertFalse(node.context().maintenanceRegistry().isMaintenanceMode()); + gridIdxs = IntStream.range(0, GRIDS_NUM).boxed().collect(Collectors.toList()); + } + else { + String nids = grids.size() == 1 + ? grids.iterator().next().localNode().id().toString() + : grids.stream().map(g -> g.localNode().id().toString()).collect(Collectors.joining(",")); - checkIndexes(CACHE_NAME_NO_GRP); + assertEquals(EXIT_CODE_OK, execute("--cache", "schedule_indexes_rebuild", + grids.size() == 1 ? "--node-id" : "--node-ids", nids, "--cache-names", CACHE_NAME_NO_GRP)); + } + + for (Integer gridIdx : gridIdxs) { + IgniteEx node = grid(gridIdx); + + checkIndexesRebuildScheduled(node, singletonMap(CU.cacheId(CACHE_NAME_NO_GRP), indexes(node, CACHE_NAME_NO_GRP))); + + node.close(); + + node = startGrid(gridIdx); + + assertTrue(node.context().maintenanceRegistry().isMaintenanceMode()); + + assertTrue(waitForIndexesRebuild(node)); + + node.close(); + + node = startGrid(gridIdx); + + assertFalse(node.context().maintenanceRegistry().isMaintenanceMode()); + + checkIndexes(CACHE_NAME_NO_GRP); + } } /** @@ -275,14 +378,25 @@ public class GridCommandHandlerScheduleIndexRebuildTest extends GridCommandHandl * @param specifyNodeId If {@code true} then execute rebuild only on one node. */ private void testCorruptedIndexRebuild(boolean withCacheGroup, boolean specifyNodeId) throws Exception { - IgniteEx firstNode = grid(0); + testCorruptedIndexRebuild(withCacheGroup, specifyNodeId ? Collections.singletonList(0) : null); + } + + /** + * Checks that corrupted index is successfully rebuilt by the command. + * + * @param withCacheGroup If {@code true} creates a cache with a cache group. + * @param nodeIdxs Nodes indexes of the nodes to launch on. If {@code Null}, no node ids is passed. If empty, + * '--all-nodes' passed. Otherwise, '--node-id' or '--node-ids' is used. + */ + private void testCorruptedIndexRebuild(boolean withCacheGroup, @Nullable List<Integer> nodeIdxs) throws Exception { + IgniteEx ig = grid(0); String cacheName = "tmpCache"; try { - createAndFillCache(firstNode, cacheName, withCacheGroup ? "tmpGrp" : null); + createAndFillCache(ig, cacheName, withCacheGroup ? "tmpGrp" : null); - breakSqlIndex(firstNode.cachex(cacheName), 1, null); + breakSqlIndex(ig.cachex(cacheName), 1, null); injectTestSystemOut(); @@ -295,18 +409,28 @@ public class GridCommandHandlerScheduleIndexRebuildTest extends GridCommandHandl List<String> args = new ArrayList<>(); args.add("--cache"); args.add("schedule_indexes_rebuild"); - if (specifyNodeId) { + + if (F.isEmpty(nodeIdxs)) { + if (nodeIdxs != null) + args.add("--all-nodes"); + + nodeIdxs = IntStream.range(0, GRIDS_NUM).boxed().collect(Collectors.toList()); + } + else if (nodeIdxs.size() == 1) { args.add("--node-id"); - args.add(firstNode.localNode().id().toString()); + args.add(grid(nodeIdxs.get(0)).localNode().id().toString()); + } + else { + args.add("--node-ids"); + args.add(nodeIdxs.stream().map(idx -> grid(idx).localNode().id().toString()).collect(Collectors.joining(","))); } + args.add("--cache-names"); args.add(cacheName); assertEquals(EXIT_CODE_OK, execute(args.toArray(new String[0]))); - int nodeCount = specifyNodeId ? 1 : GRIDS_NUM; - - for (int i = 0; i < nodeCount; i++) { + for (int i : nodeIdxs) { IgniteEx grid = grid(i); checkIndexesRebuildScheduled(grid, singletonMap(CU.cacheId(cacheName), indexes(grid, cacheName))); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandUtils.java index 76e37070e52..93a8890d570 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandUtils.java @@ -497,7 +497,7 @@ public class CommandUtils { } /** */ - public static Collection<GridClientNode> nodeOrNull(@Nullable UUID nodeId, Collection<GridClientNode> nodes) { + public static @Nullable Collection<GridClientNode> nodeOrNull(@Nullable UUID nodeId, Collection<GridClientNode> nodes) { return nodeId == null ? null : node(nodeId, nodes); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommand.java index 224c957159f..56abe7c175d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommand.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.ignite.internal.client.GridClientNode; @@ -44,7 +45,7 @@ public class CacheIndexesForceRebuildCommand public static final String PREF_CACHES_NOT_FOUND = "WARNING: These caches were not found:"; /** */ - private static final String PREF_GROUPS_NOT_FOUND = "WARNING: These cache groups were not found:"; + public static final String PREF_GROUPS_NOT_FOUND = "WARNING: These cache groups were not found:"; /** */ public static final String PREF_REBUILD_STARTED = "Indexes rebuild was started for these caches:"; @@ -57,6 +58,9 @@ public class CacheIndexesForceRebuildCommand public static final String PREF_REBUILD_NOT_STARTED = "WARNING: Indexes rebuild was not started for " + "any cache on the following nodes. Check the command input:"; + /** */ + public static final String PREF_SCHEDULED = "Indexes rebuild was scheduled for these caches:"; + /** {@inheritDoc} */ @Override public String description() { return "Triggers rebuild of all indexes for specified caches or cache groups"; @@ -92,7 +96,7 @@ public class CacheIndexesForceRebuildCommand } if (F.isEmpty(res)) - throw new IllegalArgumentException("Please, specify oat least one server node"); + throw new IllegalArgumentException("Please, specify at least one server node"); return res; } @@ -115,12 +119,12 @@ public class CacheIndexesForceRebuildCommand Set<UUID> notStarted = new HashSet<>(); results.forEach((nodeId, res) -> { - storeCacheResults(notFound, res.notFoundCacheNames(), nodeId); + storeEntryToNodesResults(notFound, res.notFoundCacheNames(), nodeId); - storeCacheResults(rebuilding, res.cachesWithRebuildInProgress(), nodeId); + storeEntryToNodesResults(rebuilding, res.cachesWithRebuildInProgress(), nodeId); if (!F.isEmpty(res.cachesWithStartedRebuild())) - storeCacheResults(started, res.cachesWithStartedRebuild(), nodeId); + storeEntryToNodesResults(started, res.cachesWithStartedRebuild(), nodeId); else notStarted.add(nodeId); }); @@ -188,7 +192,7 @@ public class CacheIndexesForceRebuildCommand } /** */ - private static <T> void storeCacheResults(Map<T, Set<UUID>> to, Collection<T> keys, UUID nodeId) { + static <T> void storeEntryToNodesResults(Map<T, Set<UUID>> to, Collection<T> keys, UUID nodeId) { if (F.isEmpty(keys)) return; @@ -212,30 +216,35 @@ public class CacheIndexesForceRebuildCommand } /** */ - private static void printBlock(SB b, String header, Map<?, ? extends Collection<UUID>> data) { + static void printBlock(SB b, String header, Map<?, ? extends Collection<UUID>> data, BiConsumer<SB, Object> cacheInfoPrinter) { printHeader(b, header); data.forEach((cacheInfo, nodes) -> { printEntryNewLine(b); - printCacheInfo(b, cacheInfo); + cacheInfoPrinter.accept(b, cacheInfo); b.a(" on nodes ").a(nodeIdsString(nodes)).a('.'); }); } /** */ - private static void printEntryNewLine(SB b) { + static void printBlock(SB b, String header, Map<?, ? extends Collection<UUID>> data) { + printBlock(b, header, data, CacheIndexesForceRebuildCommand::printCacheInfo); + } + + /** */ + static void printEntryNewLine(SB b) { b.a(U.nl()).a(INDENT); } /** */ - private static String nodeIdsString(Collection<UUID> nodes) { + static String nodeIdsString(Collection<UUID> nodes) { return nodes.stream().map(uuid -> '\'' + uuid.toString() + '\'').collect(Collectors.joining(", ")); } /** */ - private static void printHeader(SB b, String header) { + static void printHeader(SB b, String header) { b.a(U.nl()).a(U.nl()).a(header); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommandArg.java index 111e9f24d22..3eb8a0c837f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommandArg.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheIndexesForceRebuildCommandArg.java @@ -34,7 +34,8 @@ public class CacheIndexesForceRebuildCommandArg extends IgniteDataTransferObject private static final long serialVersionUID = 0; /** */ - @Argument(description = "Specify node for indexes rebuild (deprecated. Use --node-ids instead)", example = "nodeId") + @Argument(description = "Specify node for indexes rebuild (deprecated. Use --node-ids or --all-nodes instead)", + example = "nodeId") private UUID nodeId; /** */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommand.java index ccf845786f8..0b9fe5ffc6d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommand.java @@ -18,19 +18,46 @@ package org.apache.ignite.internal.management.cache; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.apache.ignite.internal.client.GridClientNode; +import org.apache.ignite.internal.management.api.CommandUtils; import org.apache.ignite.internal.management.api.ComputeCommand; +import org.apache.ignite.internal.util.GridStringBuilder; +import org.apache.ignite.internal.util.lang.IgnitePair; import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.SB; import static org.apache.ignite.internal.management.api.CommandUtils.INDENT; import static org.apache.ignite.internal.management.api.CommandUtils.nodeOrAll; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_CACHES_NOT_FOUND; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_GROUPS_NOT_FOUND; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.PREF_SCHEDULED; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.nodeIdsString; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.printBlock; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.printEntryNewLine; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.printHeader; +import static org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand.storeEntryToNodesResults; /** Index rebuild via the maintenance mode. */ public class CacheScheduleIndexesRebuildCommand implements ComputeCommand<CacheScheduleIndexesRebuildCommandArg, ScheduleIndexRebuildTaskRes> { + /** */ + public static final String PREF_INDEXES_NOT_FOUND = "WARNING: These indexes were not found:"; + + /** */ + public static final String PREF_REBUILD_NOT_SCHEDULED = "WARNING: Indexes rebuild was not scheduled for any cache. " + + "Check command input."; + + /** */ + public static final String PREF_REBUILD_NOT_SCHEDULED_MULTI = "WARNING: Indexes rebuild was not scheduled for " + + "any cache on the following nodes. Check command input:"; + /** {@inheritDoc} */ @Override public String description() { return "Schedules rebuild of the indexes for specified caches via the Maintenance Mode. " + @@ -49,34 +76,100 @@ public class CacheScheduleIndexesRebuildCommand /** {@inheritDoc} */ @Override public Collection<GridClientNode> nodes(Collection<GridClientNode> nodes, CacheScheduleIndexesRebuildCommandArg arg) { - return nodeOrAll(arg.nodeId(), nodes); + if (arg.allNodes() || F.isEmpty(arg.nodeIds()) && arg.nodeId() == null) + return nodes; + + nodeOrAll(arg.nodeId(), nodes); + + return CommandUtils.nodes(arg.nodeId() == null ? arg.nodeIds() : new UUID[] {arg.nodeId()}, nodes); } /** {@inheritDoc} */ @Override public void printResult( CacheScheduleIndexesRebuildCommandArg arg, - ScheduleIndexRebuildTaskRes res0, + ScheduleIndexRebuildTaskRes results, Consumer<String> printer ) { - res0.results().forEach((nodeId, res) -> { - printMissed(printer, "WARNING: These caches were not found:", res.notFoundCacheNames()); - printMissed(printer, "WARNING: These cache groups were not found:", res.notFoundGroupNames()); + if (arg.nodeId() != null) { + printSingleResult(results, printer); + + return; + } + + Map<String, Set<UUID>> missedCaches = new HashMap<>(); + Map<String, Set<UUID>> missedGroups = new HashMap<>(); + Map<String, Set<UUID>> notFoundIndexes = new HashMap<>(); + Map<String, Set<UUID>> scheduled = new HashMap<>(); + Set<UUID> notScheduled = new HashSet<>(); + + results.results().forEach((nodeId, res) -> { + storeEntryToNodesResults(missedCaches, res.notFoundCacheNames(), nodeId); + + storeEntryToNodesResults(missedGroups, res.notFoundGroupNames(), nodeId); + + storeEntryToNodesResults(notFoundIndexes, extractCacheIndexNames(res.notFoundIndexes()), nodeId); + + if (hasAtLeastOneIndex(res.cacheToIndexes())) + storeEntryToNodesResults(scheduled, extractCacheIndexNames(res.cacheToIndexes()), nodeId); + else + notScheduled.add(nodeId); + }); + + SB b = new SB(); + + if (!F.isEmpty(missedCaches)) + printBlock(b, PREF_CACHES_NOT_FOUND, missedCaches, GridStringBuilder::a); + + if (!F.isEmpty(missedGroups)) + printBlock(b, PREF_GROUPS_NOT_FOUND, missedGroups, GridStringBuilder::a); - if (!F.isEmpty(res.notFoundIndexes()) && hasAtLeastOneIndex(res.notFoundIndexes())) { - String warning = "WARNING: These indexes were not found:"; + if (!F.isEmpty(notFoundIndexes)) + printBlock(b, PREF_INDEXES_NOT_FOUND, notFoundIndexes, GridStringBuilder::a); - printer.accept(warning); + if (!F.isEmpty(notScheduled)) { + printHeader(b, PREF_REBUILD_NOT_SCHEDULED_MULTI); + + printEntryNewLine(b); + + b.a(nodeIdsString(notScheduled)); + } + + if (!F.isEmpty(scheduled)) + printBlock(b, PREF_SCHEDULED, scheduled, GridStringBuilder::a); + + printer.accept(b.toString().trim()); + } + + /** */ + private static Collection<String> extractCacheIndexNames(Map<String, Set<String>> cacheIndexes) { + return F.flatCollections(cacheIndexes.entrySet().stream().map(cIdxs -> cIdxs.getValue().stream() + .map(idx -> indexAndCacheInfo(cIdxs.getKey(), idx)).collect(Collectors.toList())).collect(Collectors.toList())); + } + + /** */ + private static String indexAndCacheInfo(String cache, String index) { + return '\'' + index + "' (of cache '" + cache + "')"; + } + + /** */ + private static void printSingleResult(ScheduleIndexRebuildTaskRes result, Consumer<String> printer) { + result.results().forEach((nodeId, res) -> { + printMissed(printer, PREF_CACHES_NOT_FOUND, res.notFoundCacheNames()); + printMissed(printer, PREF_GROUPS_NOT_FOUND, res.notFoundGroupNames()); + + if (hasAtLeastOneIndex(res.notFoundIndexes())) { + printer.accept(PREF_INDEXES_NOT_FOUND); printCachesAndIndexes(res.notFoundIndexes(), printer); } if (!F.isEmpty(res.cacheToIndexes()) && hasAtLeastOneIndex(res.cacheToIndexes())) { - printer.accept("Indexes rebuild was scheduled for these caches:"); + printer.accept(PREF_SCHEDULED); printCachesAndIndexes(res.cacheToIndexes(), printer); } else - printer.accept("WARNING: Indexes rebuild was not scheduled for any cache. Check command input."); + printer.accept(PREF_REBUILD_NOT_SCHEDULED); printer.accept(""); }); @@ -89,7 +182,7 @@ public class CacheScheduleIndexesRebuildCommand * @param message Message. * @param missed Missed caches or cache groups' names. */ - private void printMissed(Consumer<String> printer, String message, Set<String> missed) { + private static void printMissed(Consumer<String> printer, String message, Set<String> missed) { if (F.isEmpty(missed)) return; @@ -120,8 +213,23 @@ public class CacheScheduleIndexesRebuildCommand * @return {@code true} if has at least one index in the map, {@code false} otherwise. */ private static boolean hasAtLeastOneIndex(Map<String, Set<String>> cacheToIndexes) { - return cacheToIndexes.values().stream() + return !F.isEmpty(cacheToIndexes) && cacheToIndexes.values().stream() .anyMatch(indexes -> !indexes.isEmpty()); } + /** */ + static <T> void storeCacheAndIndexResults(Map<IgnitePair<T>, Set<UUID>> to, Map<T, Set<T>> values, UUID nodeId) { + if (F.isEmpty(values)) + return; + + values.forEach((cache, indexes) -> indexes.forEach(idx -> + to.compute(new IgnitePair<>(cache, idx), (c0, idxs0) -> { + if (idxs0 == null) + idxs0 = new HashSet<>(); + + idxs0.add(nodeId); + + return idxs0; + }))); + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommandArg.java index 1c609ec27c0..94894a5bb3d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommandArg.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheScheduleIndexesRebuildCommandArg.java @@ -36,6 +36,7 @@ import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; /** */ +@ArgumentGroup(value = {"nodeIds", "allNodes", "nodeId"}, onlyOneOf = true, optional = true) @ArgumentGroup(value = {"cacheNames", "groupNames"}, optional = false) public class CacheScheduleIndexesRebuildCommandArg extends IgniteDataTransferObject { /** */ @@ -46,11 +47,22 @@ public class CacheScheduleIndexesRebuildCommandArg extends IgniteDataTransferObj /** */ @Argument( - description = "(Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes", - example = "nodeId", - optional = true) + description = "(Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes " + + "(deprecated. Use --node-ids or --all-nodes instead)", + example = "nodeId") private UUID nodeId; + /** */ + @Argument( + description = "Comma-separated list of nodes ids to schedule index rebuild on", + example = "nodeId1,...nodeIdN" + ) + private UUID[] nodeIds; + + /** Flag to launch index rebuild on all nodes. */ + @Argument(description = "Rebuild index on all nodes") + private boolean allNodes; + /** */ @Argument(description = "Comma-separated list of cache names with optionally specified indexes. " + "If indexes are not specified then all indexes of the cache will be scheduled for the rebuild operation. " + @@ -73,6 +85,8 @@ public class CacheScheduleIndexesRebuildCommandArg extends IgniteDataTransferObj U.writeString(out, cacheNames); U.writeArray(out, groupNames); U.writeMap(out, cacheToIndexes); + U.writeArray(out, nodeIds); + out.writeBoolean(allNodes); } /** {@inheritDoc} */ @@ -81,6 +95,8 @@ public class CacheScheduleIndexesRebuildCommandArg extends IgniteDataTransferObj cacheNames = U.readString(in); groupNames = U.readArray(in, String.class); cacheToIndexes = U.readMap(in); + nodeIds = U.readArray(in, UUID.class); + allNodes = in.readBoolean(); } /** */ @@ -128,6 +144,26 @@ public class CacheScheduleIndexesRebuildCommandArg extends IgniteDataTransferObj this.nodeId = nodeId; } + /** */ + public UUID[] nodeIds() { + return nodeIds; + } + + /** */ + public void allNodes(boolean allNodes) { + this.allNodes = allNodes; + } + + /** */ + public boolean allNodes() { + return allNodes; + } + + /** */ + public void nodeIds(UUID[] nodeIds) { + this.nodeIds = nodeIds; + } + /** */ public String cacheNames() { return cacheNames; diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_cache_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_cache_help.output index 3b7b9111815..2fc51183618 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_cache_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_cache_help.output @@ -100,7 +100,7 @@ Arguments: --cache help --yes control.(sh|bat) --cache indexes_force_rebuild --node-id nodeId|--node-ids nodeId1,...nodeIdN|--all-nodes --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN Parameters: - --node-id nodeId - Specify node for indexes rebuild (deprecated. Use --node-ids instead). + --node-id nodeId - Specify node for indexes rebuild (deprecated. Use --node-ids or --all-nodes instead). --node-ids nodeId1,...nodeIdN - Comma-separated list of nodes ids to run index rebuild on. --all-nodes - Rebuild index on all nodes. --cache-names cacheName1,...cacheNameN - Comma-separated list of cache names for which indexes should be rebuilt. @@ -114,10 +114,12 @@ Arguments: --cache help --yes --all-caches - applies operation to all user caches. Schedules rebuild of the indexes for specified caches via the Maintenance Mode. Schedules rebuild of specified caches and cache-groups: - control.(sh|bat) --cache schedule_indexes_rebuild [--node-id nodeId] --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN + control.(sh|bat) --cache schedule_indexes_rebuild [--node-id nodeId|--node-ids nodeId1,...nodeIdN|--all-nodes] --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN Parameters: - --node-id nodeId - (Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes. + --node-id nodeId - (Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes (deprecated. Use --node-ids or --all-nodes instead). + --node-ids nodeId1,...nodeIdN - Comma-separated list of nodes ids to schedule index rebuild on. + --all-nodes - Rebuild index on all nodes. --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] - Comma-separated list of cache names with optionally specified indexes. If indexes are not specified then all indexes of the cache will be scheduled for the rebuild operation. Can be used simultaneously with cache group names. --group-names groupName1,groupName2,...groupNameN - Comma-separated list of cache group names for which indexes should be scheduled for the rebuild. Can be used simultaneously with cache names. diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_cache_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_cache_help.output index 3b7b9111815..2fc51183618 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_cache_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_cache_help.output @@ -100,7 +100,7 @@ Arguments: --cache help --yes control.(sh|bat) --cache indexes_force_rebuild --node-id nodeId|--node-ids nodeId1,...nodeIdN|--all-nodes --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN Parameters: - --node-id nodeId - Specify node for indexes rebuild (deprecated. Use --node-ids instead). + --node-id nodeId - Specify node for indexes rebuild (deprecated. Use --node-ids or --all-nodes instead). --node-ids nodeId1,...nodeIdN - Comma-separated list of nodes ids to run index rebuild on. --all-nodes - Rebuild index on all nodes. --cache-names cacheName1,...cacheNameN - Comma-separated list of cache names for which indexes should be rebuilt. @@ -114,10 +114,12 @@ Arguments: --cache help --yes --all-caches - applies operation to all user caches. Schedules rebuild of the indexes for specified caches via the Maintenance Mode. Schedules rebuild of specified caches and cache-groups: - control.(sh|bat) --cache schedule_indexes_rebuild [--node-id nodeId] --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN + control.(sh|bat) --cache schedule_indexes_rebuild [--node-id nodeId|--node-ids nodeId1,...nodeIdN|--all-nodes] --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] --group-names groupName1,groupName2,...groupNameN Parameters: - --node-id nodeId - (Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes. + --node-id nodeId - (Optional) Specify node for indexes rebuild. If not specified, schedules rebuild on all nodes (deprecated. Use --node-ids or --all-nodes instead). + --node-ids nodeId1,...nodeIdN - Comma-separated list of nodes ids to schedule index rebuild on. + --all-nodes - Rebuild index on all nodes. --cache-names cacheName[index1,...indexN],cacheName2,cacheName3[index1] - Comma-separated list of cache names with optionally specified indexes. If indexes are not specified then all indexes of the cache will be scheduled for the rebuild operation. Can be used simultaneously with cache group names. --group-names groupName1,groupName2,...groupNameN - Comma-separated list of cache group names for which indexes should be scheduled for the rebuild. Can be used simultaneously with cache names.