From ab917273c0d0bb321044862375899a3a582bb27c Mon Sep 17 00:00:00 2001 From: Nikolay Date: Fri, 2 Jun 2023 11:29:52 +0300 Subject: [PATCH] IGNITE-15629 Cache contention command implemented (#10744) --- .../commandline/cache/CacheContention.java | 145 ------------------ .../commandline/cache/CacheSubcommands.java | 3 +- .../internal/management/api/CommandUtils.java | 5 + .../management/cache/CacheCommand.java | 1 + .../cache/CacheContentionCommand.java | 61 ++++++++ .../cache/CacheContentionCommandArg.java | 92 +++++++++++ .../management/metric/MetricCommand.java | 4 +- .../MetricConfigureHistogramCommand.java | 4 +- .../metric/MetricConfigureHitrateCommand.java | 4 +- .../visor/verify/VisorContentionTask.java | 11 +- .../visor/verify/VisorContentionTaskArg.java | 84 ---------- ...andlerClusterByClassTest_cache_help.output | 4 +- 12 files changed, 175 insertions(+), 243 deletions(-) delete mode 100644 modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommand.java create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommandArg.java delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/visor/verify/VisorContentionTaskArg.java diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java deleted file mode 100644 index dd274b3c6fd71..0000000000000 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.commandline.cache; - -import java.util.UUID; -import org.apache.ignite.IgniteLogger; -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.management.api.CommandUtils; -import org.apache.ignite.internal.processors.cache.verify.ContentionInfo; -import org.apache.ignite.internal.visor.verify.VisorContentionTask; -import org.apache.ignite.internal.visor.verify.VisorContentionTaskArg; -import org.apache.ignite.internal.visor.verify.VisorContentionTaskResult; -import static org.apache.ignite.internal.commandline.CommandLogger.optional; -import static org.apache.ignite.internal.commandline.TaskExecutor.BROADCAST_UUID; -import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode; -import static org.apache.ignite.internal.commandline.cache.CacheCommands.OP_NODE_ID; -import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.CONTENTION; - -/** - * Cache contention detection subcommand. - */ -public class CacheContention extends AbstractCommand { - /** {@inheritDoc} */ - @Override public void printUsage(IgniteLogger logger) { - String description = "Show the keys that are point of contention for multiple transactions."; - - usageCache(logger, CONTENTION, description, null, "minQueueSize", - OP_NODE_ID, optional("maxPrint")); - } - - /** - * Container for command arguments. - */ - public class Arguments { - /** Node id. */ - private UUID nodeId; - - /** Min queue size. */ - private int minQueueSize; - - /** Max print. */ - private int maxPrint; - - /** - * - */ - public Arguments(UUID nodeId, int minQueueSize, int maxPrint) { - this.nodeId = nodeId; - this.minQueueSize = minQueueSize; - this.maxPrint = maxPrint; - } - - /** - * @return Node id. - */ - public UUID nodeId() { - return nodeId; - } - - /** - * @return Min queue size. - */ - public int minQueueSize() { - return minQueueSize; - } - - /** - * @return Max print. - */ - public int maxPrint() { - return maxPrint; - } - } - - /** - * Command parsed arguments. - */ - private Arguments args; - - /** {@inheritDoc} */ - @Override public Arguments arg() { - return args; - } - - /** {@inheritDoc} */ - @Override public Object execute(GridClientConfiguration clientCfg, IgniteLogger logger) throws Exception { - VisorContentionTaskArg taskArg = new VisorContentionTaskArg(args.minQueueSize(), args.maxPrint()); - - UUID nodeId = args.nodeId() == null ? BROADCAST_UUID : args.nodeId(); - - VisorContentionTaskResult res; - - try (GridClient client = Command.startClient(clientCfg);) { - res = executeTaskByNameOnNode(client, VisorContentionTask.class.getName(), taskArg, nodeId, clientCfg); - } - - CommandUtils.printErrors(res.exceptions(), "Contention check failed on nodes:", logger::info); - - for (ContentionInfo info : res.getInfos()) - info.print(); - - return res; - } - - /** {@inheritDoc} */ - @Override public void parseArguments(CommandArgIterator argIter) { - int minQueueSize = Integer.parseInt(argIter.nextArg("Min queue size expected")); - - UUID nodeId = null; - - if (argIter.hasNextSubArg()) - nodeId = UUID.fromString(argIter.nextArg("")); - - int maxPrint = 10; - - if (argIter.hasNextSubArg()) - maxPrint = Integer.parseInt(argIter.nextArg("")); - - args = new Arguments(nodeId, minQueueSize, maxPrint); - } - - /** {@inheritDoc} */ - @Override public String name() { - return CONTENTION.text().toUpperCase(); - } -} diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java index 743f2da7fc78f..ee6bb6376e5fe 100644 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/cache/CacheSubcommands.java @@ -26,6 +26,7 @@ import org.apache.ignite.internal.commandline.cache.argument.IndexRebuildCommandArg; import org.apache.ignite.internal.management.cache.CacheCheckIndexInlineSizesCommand; import org.apache.ignite.internal.management.cache.CacheClearCommand; +import org.apache.ignite.internal.management.cache.CacheContentionCommand; import org.apache.ignite.internal.management.cache.CacheCreateCommand; import org.apache.ignite.internal.management.cache.CacheDestroyCommand; import org.apache.ignite.internal.management.cache.CacheIndexesForceRebuildCommand; @@ -86,7 +87,7 @@ public enum CacheSubcommands { /** * Prints info about contended keys (the keys concurrently locked from multiple transactions). */ - CONTENTION("contention", null, new CacheContention()), + CONTENTION(new CacheContentionCommand()), /** * Collect information on the distribution of partitions. 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 3ba14f20bf59f..d128e3a24d3f2 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 @@ -287,6 +287,11 @@ public static T parseVal(String val, Class type) { .orElse(null); } + /** */ + public static Collection nodeOrNull(@Nullable UUID nodeId) { + return nodeId == null ? null : Collections.singleton(nodeId); + } + /** * @param nodes Nodes. * @return Server nodes. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheCommand.java index ff53941feb0c6..5fb4cc7555067 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheCommand.java @@ -32,6 +32,7 @@ public CacheCommand() { new CacheClearCommand(), new CacheValidateIndexesCommand(), new CacheCheckIndexInlineSizesCommand(), + new CacheContentionCommand(), new CacheResetLostPartitionsCommand(), new CacheIndexesListCommand(), new CacheIndexesRebuildStatusCommand(), diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommand.java new file mode 100644 index 0000000000000..a1c15092607fa --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommand.java @@ -0,0 +1,61 @@ +/* + * 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.management.cache; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; +import org.apache.ignite.internal.management.api.CommandUtils; +import org.apache.ignite.internal.management.api.ComputeCommand; +import org.apache.ignite.internal.processors.cache.verify.ContentionInfo; +import org.apache.ignite.internal.util.typedef.T3; +import org.apache.ignite.internal.visor.verify.VisorContentionTask; +import org.apache.ignite.internal.visor.verify.VisorContentionTaskResult; + +/** */ +public class CacheContentionCommand implements ComputeCommand { + /** {@inheritDoc} */ + @Override public String description() { + return "Show the keys that are point of contention for multiple transactions"; + } + + /** {@inheritDoc} */ + @Override public Class argClass() { + return CacheContentionCommandArg.class; + } + + /** {@inheritDoc} */ + @Override public Class taskClass() { + return VisorContentionTask.class; + } + + /** {@inheritDoc} */ + @Override public Collection nodes(Map> nodes, CacheContentionCommandArg arg) { + return arg.nodeId() == null ? nodes.keySet() : Collections.singleton(arg.nodeId()); + } + + /** {@inheritDoc} */ + @Override public void printResult(CacheContentionCommandArg arg, VisorContentionTaskResult res, Consumer printer) { + CommandUtils.printErrors(res.exceptions(), "Contention check failed on nodes:", printer); + + for (ContentionInfo info : res.getInfos()) + info.print(); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommandArg.java b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommandArg.java new file mode 100644 index 0000000000000..e039f43e4ecce --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/CacheContentionCommandArg.java @@ -0,0 +1,92 @@ +/* + * 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.management.cache; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.UUID; +import org.apache.ignite.internal.dto.IgniteDataTransferObject; +import org.apache.ignite.internal.management.api.Argument; +import org.apache.ignite.internal.management.api.Positional; +import org.apache.ignite.internal.util.typedef.internal.U; + +/** */ +public class CacheContentionCommandArg extends IgniteDataTransferObject { + /** */ + private static final long serialVersionUID = 0; + + /** Min queue size. */ + @Positional + @Argument(example = "minQueueSize") + private int minQueueSize; + + /** Node id. */ + @Positional + @Argument(optional = true, example = "nodeId") + private UUID nodeId; + + /** Max print. */ + @Positional + @Argument(optional = true, example = "maxPrint") + private int maxPrint = 10; + + /** {@inheritDoc} */ + @Override protected void writeExternalData(ObjectOutput out) throws IOException { + U.writeUuid(out, nodeId); + out.writeInt(minQueueSize); + out.writeInt(maxPrint); + } + + /** {@inheritDoc} */ + @Override protected void readExternalData(byte protoVer, ObjectInput in) throws IOException, ClassNotFoundException { + nodeId = U.readUuid(in); + minQueueSize = in.readInt(); + maxPrint = in.readInt(); + } + + /** */ + public UUID nodeId() { + return nodeId; + } + + /** */ + public void nodeId(UUID nodeId) { + this.nodeId = nodeId; + } + + /** */ + public int minQueueSize() { + return minQueueSize; + } + + /** */ + public void minQueueSize(int minQueueSize) { + this.minQueueSize = minQueueSize; + } + + /** */ + public int maxPrint() { + return maxPrint; + } + + /** */ + public void maxPrint(int maxPrint) { + this.maxPrint = maxPrint; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricCommand.java index 4a2ebab5eef93..a09c423aeff83 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricCommand.java @@ -19,7 +19,6 @@ import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -31,6 +30,7 @@ import org.apache.ignite.internal.visor.metric.VisorMetricTask; import static java.util.Arrays.asList; import static org.apache.ignite.internal.management.SystemViewCommand.printTable; +import static org.apache.ignite.internal.management.api.CommandUtils.nodeOrNull; import static org.apache.ignite.internal.visor.systemview.VisorSystemViewTask.SimpleType.STRING; /** */ @@ -61,7 +61,7 @@ public MetricCommand() { /** {@inheritDoc} */ @Override public Collection nodes(Map> nodes, MetricCommandArg arg) { - return arg.nodeId() == null ? null : Collections.singleton(arg.nodeId()); + return nodeOrNull(arg.nodeId()); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHistogramCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHistogramCommand.java index 0a93fd5f9b5d7..a1a9368e131c9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHistogramCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHistogramCommand.java @@ -18,12 +18,12 @@ package org.apache.ignite.internal.management.metric; import java.util.Collection; -import java.util.Collections; import java.util.Map; import java.util.UUID; import org.apache.ignite.internal.management.api.ComputeCommand; import org.apache.ignite.internal.util.typedef.T3; import org.apache.ignite.internal.visor.metric.VisorMetricTask; +import static org.apache.ignite.internal.management.api.CommandUtils.nodeOrNull; /** */ public class MetricConfigureHistogramCommand implements ComputeCommand> { @@ -44,6 +44,6 @@ public class MetricConfigureHistogramCommand implements ComputeCommand nodes(Map> nodes, MetricCommandArg arg) { - return arg.nodeId() == null ? null : Collections.singleton(arg.nodeId()); + return nodeOrNull(arg.nodeId()); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHitrateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHitrateCommand.java index d7bc1d87e822c..38f6033469501 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHitrateCommand.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/management/metric/MetricConfigureHitrateCommand.java @@ -18,12 +18,12 @@ package org.apache.ignite.internal.management.metric; import java.util.Collection; -import java.util.Collections; import java.util.Map; import java.util.UUID; import org.apache.ignite.internal.management.api.ComputeCommand; import org.apache.ignite.internal.util.typedef.T3; import org.apache.ignite.internal.visor.metric.VisorMetricTask; +import static org.apache.ignite.internal.management.api.CommandUtils.nodeOrNull; /** */ public class MetricConfigureHitrateCommand implements ComputeCommand> { @@ -44,6 +44,6 @@ public class MetricConfigureHitrateCommand implements ComputeCommand nodes(Map> nodes, MetricCommandArg arg) { - return arg.nodeId() == null ? null : Collections.singleton(arg.nodeId()); + return nodeOrNull(arg.nodeId()); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/verify/VisorContentionTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/verify/VisorContentionTask.java index 4e7e12c2ff102..994edda447b97 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/visor/verify/VisorContentionTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/verify/VisorContentionTask.java @@ -24,6 +24,7 @@ import java.util.UUID; import org.apache.ignite.IgniteException; import org.apache.ignite.compute.ComputeJobResult; +import org.apache.ignite.internal.management.cache.CacheContentionCommandArg; import org.apache.ignite.internal.processors.cache.verify.ContentionClosure; import org.apache.ignite.internal.processors.cache.verify.ContentionInfo; import org.apache.ignite.internal.processors.task.GridInternal; @@ -36,7 +37,7 @@ * */ @GridInternal -public class VisorContentionTask extends VisorMultiNodeTask { /** */ private static final long serialVersionUID = 0L; @@ -57,14 +58,14 @@ public class VisorContentionTask extends VisorMultiNodeTask job(VisorContentionTaskArg arg) { + @Override protected VisorJob job(CacheContentionCommandArg arg) { return new VisorContentionJob(arg, debug); } /** * */ - private static class VisorContentionJob extends VisorJob { + private static class VisorContentionJob extends VisorJob { /** */ private static final long serialVersionUID = 0L; @@ -72,12 +73,12 @@ private static class VisorContentionJob extends VisorJob