blob: 6060b1fb840cefe4b6669140fd822838a1906f3f [file] [log] [blame]
/*
* 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;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import org.apache.ignite.internal.client.GridClient;
import org.apache.ignite.internal.client.GridClientConfiguration;
import org.apache.ignite.internal.commandline.AbstractCommand;
import org.apache.ignite.internal.commandline.Command;
import org.apache.ignite.internal.commandline.CommandArgIterator;
import org.apache.ignite.internal.commandline.TaskExecutor;
import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
import org.apache.ignite.internal.commandline.cache.argument.IndexForceRebuildCommandArg;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.internal.visor.cache.index.IndexForceRebuildTask;
import org.apache.ignite.internal.visor.cache.index.IndexForceRebuildTaskArg;
import org.apache.ignite.internal.visor.cache.index.IndexForceRebuildTaskRes;
import org.apache.ignite.internal.visor.cache.index.IndexRebuildStatusInfoContainer;
import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
import static org.apache.ignite.internal.commandline.CommandLogger.or;
import static org.apache.ignite.internal.commandline.cache.argument.IndexForceRebuildCommandArg.CACHE_NAMES;
import static org.apache.ignite.internal.commandline.cache.argument.IndexForceRebuildCommandArg.GROUP_NAMES;
import static org.apache.ignite.internal.commandline.cache.argument.IndexForceRebuildCommandArg.NODE_ID;
/**
* Cache subcommand that triggers indexes force rebuild.
*/
public class CacheIndexesForceRebuild extends AbstractCommand<CacheIndexesForceRebuild.Arguments> {
/** Command parsed arguments. */
private Arguments args;
/** {@inheritDoc} */
@Override public void printUsage(Logger logger) {
String desc = "Triggers rebuild of all indexes for specified caches or cache groups.";
Map<String, String> map = U.newLinkedHashMap(16);
map.put(NODE_ID.argName(), "Specify node for indexes rebuild.");
map.put(CACHE_NAMES.argName(), "Comma-separated list of cache names for which indexes should be rebuilt.");
map.put(GROUP_NAMES.argName(), "Comma-separated list of cache group names for which indexes should be rebuilt.");
usageCache(
logger,
CacheSubcommands.INDEX_FORCE_REBUILD,
desc,
map,
NODE_ID.argName() + " nodeId",
or("--cache-names cacheName1,...cacheNameN", "--group-names groupName1,...groupNameN")
);
}
/** {@inheritDoc} */
@Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
IndexForceRebuildTaskRes taskRes;
IndexForceRebuildTaskArg taskArg = new IndexForceRebuildTaskArg(args.cacheGrps, args.cacheNames);
final UUID nodeId = args.nodeId;
try (GridClient client = Command.startClient(clientCfg)) {
taskRes = TaskExecutor.executeTaskByNameOnNode(
client,
IndexForceRebuildTask.class.getName(),
taskArg,
nodeId,
clientCfg
);
}
printResult(taskRes, logger);
return taskRes;
}
/**
* @param res Rebuild task result.
* @param logger Logger to print to.
*/
private void printResult(IndexForceRebuildTaskRes res, Logger logger) {
if (!F.isEmpty(res.notFoundCacheNames())) {
String warning = args.cacheGrps == null ?
"WARNING: These caches were not found:" : "WARNING: These cache groups were not found:";
logger.info(warning);
res.notFoundCacheNames()
.stream()
.sorted()
.forEach(name -> logger.info(INDENT + name));
logger.info("");
}
if (!F.isEmpty(res.cachesWithRebuildInProgress())) {
logger.info("WARNING: These caches have indexes rebuilding in progress:");
printInfos(res.cachesWithRebuildInProgress(), logger);
logger.info("");
}
if (!F.isEmpty(res.cachesWithStartedRebuild())) {
logger.info("Indexes rebuild was started for these caches:");
printInfos(res.cachesWithStartedRebuild(), logger);
}
else
logger.info("WARNING: Indexes rebuild was not started for any cache. Check command input.");
logger.info("");
}
/** */
private void printInfos(Collection<IndexRebuildStatusInfoContainer> infos, Logger logger) {
infos.stream()
.sorted(IndexRebuildStatusInfoContainer.comparator())
.forEach(rebuildStatusInfo -> logger.info(INDENT + rebuildStatusInfo.toString()));
}
/** {@inheritDoc} */
@Override public Arguments arg() {
return args;
}
/** {@inheritDoc} */
@Override public String name() {
return CacheSubcommands.INDEX_FORCE_REBUILD.text().toUpperCase();
}
/**
* Container for command arguments.
*/
public static class Arguments {
/** Node id. */
private UUID nodeId;
/** Cache group name. */
private Set<String> cacheGrps;
/** Cache name. */
private Set<String> cacheNames;
/** */
public Arguments(UUID nodeId, Set<String> cacheGrps, Set<String> cacheNames) {
this.nodeId = nodeId;
this.cacheGrps = cacheGrps;
this.cacheNames = cacheNames;
}
/**
* @return Node id.
*/
public UUID nodeId() {
return nodeId;
}
/**
* @return Cache group to scan for, null means scanning all groups.
*/
public Set<String> cacheGrps() {
return cacheGrps;
}
/**
* @return List of caches names.
*/
public Set<String> cacheNames() {
return cacheNames;
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(Arguments.class, this);
}
}
/** {@inheritDoc} */
@Override public void parseArguments(CommandArgIterator argIterator) {
UUID nodeId = null;
Set<String> cacheGrps = null;
Set<String> cacheNames = null;
while (argIterator.hasNextSubArg()) {
String nextArg = argIterator.nextArg("");
IndexForceRebuildCommandArg arg = CommandArgUtils.of(nextArg, IndexForceRebuildCommandArg.class);
if (arg == null)
throw new IllegalArgumentException("Unknown argument: " + nextArg);
switch (arg) {
case NODE_ID:
if (nodeId != null)
throw new IllegalArgumentException(arg.argName() + " arg specified twice.");
nodeId = UUID.fromString(argIterator.nextArg("Failed to read node id."));
break;
case GROUP_NAMES:
if (cacheGrps != null)
throw new IllegalArgumentException(arg.argName() + " arg specified twice.");
cacheGrps = argIterator.nextStringSet("comma-separated list of cache group names.");
if (cacheGrps.equals(Collections.emptySet()))
throw new IllegalArgumentException(arg.argName() + " not specified.");
break;
case CACHE_NAMES:
if (cacheNames != null)
throw new IllegalArgumentException(arg.argName() + " arg specified twice.");
cacheNames = argIterator.nextStringSet("comma-separated list of cache names.");
if (cacheNames.equals(Collections.emptySet()))
throw new IllegalArgumentException(arg.argName() + " not specified.");
break;
default:
throw new IllegalArgumentException("Unknown argument: " + arg.argName());
}
}
args = new Arguments(nodeId, cacheGrps, cacheNames);
validateArguments();
}
/** */
private void validateArguments() {
if (args.nodeId == null)
throw new IllegalArgumentException(NODE_ID + " must be specified.");
if ((args.cacheGrps == null) == (args.cacheNames() == null))
throw new IllegalArgumentException("Either " + GROUP_NAMES + " or " + CACHE_NAMES + " must be specified.");
}
}