This is an automated email from the ASF dual-hosted git repository. av 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 0c5cb48 IGNITE-15702 Control.sh consistency check command should support status option (#9529) 0c5cb48 is described below commit 0c5cb48b4eac1c056caca93f85c85eeeb6ce2281 Author: Anton Vinogradov <a...@apache.org> AuthorDate: Tue Nov 9 17:06:59 2021 +0300 IGNITE-15702 Control.sh consistency check command should support status option (#9529) --- docs/_docs/tools/control-script.adoc | 22 ++++- .../consistency/ConsistencyCommand.java | 17 +++- .../consistency/ConsistencySubCommand.java | 6 +- .../ignite/util/KillCommandsCommandShTest.java | 40 ++++++++- .../cache/IgniteCacheOffheapManagerImpl.java | 14 ++-- .../visor/consistency/AbstractConsistencyTask.java | 64 +++++++++++++++ .../consistency/VisorConsistencyRepairTask.java | 48 ++--------- .../consistency/VisorConsistencyRepairTaskArg.java | 19 +++++ .../consistency/VisorConsistencyStatusTask.java | 95 ++++++++++++++++++++++ ...Result.java => VisorConsistencyTaskResult.java} | 2 +- .../main/resources/META-INF/classnames.properties | 2 +- ...ridCommandHandlerClusterByClassTest_help.output | 4 + ...andHandlerClusterByClassWithSSLTest_help.output | 4 + 13 files changed, 281 insertions(+), 56 deletions(-) diff --git a/docs/_docs/tools/control-script.adoc b/docs/_docs/tools/control-script.adoc index 24b9972..527ef0c 100644 --- a/docs/_docs/tools/control-script.adoc +++ b/docs/_docs/tools/control-script.adoc @@ -977,6 +977,8 @@ Parameters: == Cache Consistency +=== Repair + The command allows to perform cache consistency check and repair (when possible) using Read Repair approach. [tabs] @@ -999,4 +1001,22 @@ Parameters: | Parameter | Description | `cache-name`| Cache to be checked/repaired.. | `partition`| Cache's partition to be checked/repaired. -|=== \ No newline at end of file +|=== + +=== Status + +The command allows performing cache consistency check/repair operations status check. + +[tabs] +-- +tab:Unix[] +[source,shell] +---- +control.sh --enable-experimental --consistency status +---- +tab:Window[] +[source,shell] +---- +control.bat --enable-experimental --consistency status +---- +-- diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencyCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencyCommand.java index 10ef23a..46e2760 100644 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencyCommand.java +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencyCommand.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.commandline.consistency; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Logger; @@ -28,18 +29,19 @@ import org.apache.ignite.internal.commandline.Command; import org.apache.ignite.internal.commandline.CommandArgIterator; import org.apache.ignite.internal.commandline.CommandLogger; import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskArg; -import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskResult; +import org.apache.ignite.internal.visor.consistency.VisorConsistencyTaskResult; import static org.apache.ignite.internal.commandline.CommandList.CONSISTENCY; 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.consistency.ConsistencySubCommand.REPAIR; +import static org.apache.ignite.internal.commandline.consistency.ConsistencySubCommand.STATUS; import static org.apache.ignite.internal.commandline.consistency.ConsistencySubCommand.of; /** * */ -public class ConsistencyCommand extends AbstractCommand<VisorConsistencyRepairTaskArg> { +public class ConsistencyCommand extends AbstractCommand<Object> { /** Command argument. */ private VisorConsistencyRepairTaskArg cmdArg; @@ -53,7 +55,7 @@ public class ConsistencyCommand extends AbstractCommand<VisorConsistencyRepairTa StringBuilder sb = new StringBuilder(); try (GridClient client = Command.startClient(clientCfg)) { - VisorConsistencyRepairTaskResult res = executeTaskByNameOnNode( + VisorConsistencyTaskResult res = executeTaskByNameOnNode( client, cmd.taskName(), arg(), @@ -115,6 +117,13 @@ public class ConsistencyCommand extends AbstractCommand<VisorConsistencyRepairTa REPAIR.toString(), "cache-name", "partition"); + + usage( + log, + "Cache consistency check/repair operations status:", + CONSISTENCY, + Collections.emptyMap(), + STATUS.toString()); } /** {@inheritDoc} */ @@ -127,6 +136,8 @@ public class ConsistencyCommand extends AbstractCommand<VisorConsistencyRepairTa cmdArg = new VisorConsistencyRepairTaskArg(cacheName, part); } + else if (cmd == STATUS) + cmdArg = null; else throw new IllegalArgumentException("Unsupported operation."); } diff --git a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencySubCommand.java b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencySubCommand.java index a8b5fee..046ab7f 100644 --- a/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencySubCommand.java +++ b/modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencySubCommand.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.commandline.consistency; import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTask; +import org.apache.ignite.internal.visor.consistency.VisorConsistencyStatusTask; import org.jetbrains.annotations.Nullable; /** @@ -25,7 +26,10 @@ import org.jetbrains.annotations.Nullable; */ public enum ConsistencySubCommand { /** Repair. */ - REPAIR("repair", VisorConsistencyRepairTask.class.getName()); + REPAIR("repair", VisorConsistencyRepairTask.class.getName()), + + /** Status. */ + STATUS("status", VisorConsistencyStatusTask.class.getName()); /** Sub-command name. */ private final String name; diff --git a/modules/control-utility/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java b/modules/control-utility/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java index 8334084..ed19f72 100644 --- a/modules/control-utility/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java +++ b/modules/control-utility/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import org.apache.ignite.IgniteCache; import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.IgniteInterruptedCheckedException; @@ -31,6 +32,7 @@ import org.apache.ignite.internal.TestRecordingCommunicationSpi; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTask; +import org.apache.ignite.internal.visor.consistency.VisorConsistencyStatusTask; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.lang.IgniteUuid; import org.apache.ignite.spi.systemview.view.ComputeJobView; @@ -228,10 +230,13 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA cfg.setName(consistencyCancheName); cfg.setBackups(SERVER_NODE_CNT - 1); + cfg.setAffinity(new RendezvousAffinityFunction().setPartitions(1)); IgniteCache<Integer, Integer> cache = client.getOrCreateCache(cfg); - for (int i = 0; i < 10_000; i++) + int entries = 10_000; + + for (int i = 0; i < entries; i++) cache.put(i, i); AtomicInteger getCnt = new AtomicInteger(); @@ -248,7 +253,16 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA assertTrue(F.iterator0(jobs, true, repairJobFilter).hasNext()); // Found. } - int res = execute("--kill", "consistency"); + int res = execute("--consistency", "status"); + + assertEquals(EXIT_CODE_OK, res); + + assertContains(log, testOut.toString(), "Status: 1024/" + entries); + assertNotContains(log, testOut.toString(), VisorConsistencyStatusTask.NOTHING_FOUND); + + testOut.reset(); + + res = execute("--kill", "consistency"); assertEquals(EXIT_CODE_OK, res); @@ -271,16 +285,25 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA thLatch.countDown(); }); + // GridNearGetRequest messages count required to pefrom getAll() with readRepair from all nodes twice. + // First will be finished (which generates status), second will be frozen. + int twiceGetMsgCnt = SERVER_NODE_CNT * (SERVER_NODE_CNT - 1) * 2; + for (IgniteEx server : srvs) { TestRecordingCommunicationSpi spi = ((TestRecordingCommunicationSpi)server.configuration().getCommunicationSpi()); + AtomicInteger locLimit = new AtomicInteger(SERVER_NODE_CNT - 1); + spi.blockMessages((node, message) -> { if (message instanceof GridNearGetRequest) { // Get request caused by read repair operation. - if (getCnt.incrementAndGet() == SERVER_NODE_CNT) // Each node should send a get request. + // Each node should perform get twice. + if (getCnt.incrementAndGet() == twiceGetMsgCnt) th.start(); - return true; // Blocking to freeze '--consistency repair' operation. + assertTrue(getCnt.get() <= twiceGetMsgCnt); // Cancellation should stop the process. + + return locLimit.decrementAndGet() < 0; // Blocking to freeze '--consistency repair' operation (except first get). } return false; @@ -303,5 +326,14 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA spi.stopBlock(); } + + testOut.reset(); + + int res = execute("--consistency", "status"); + + assertEquals(EXIT_CODE_OK, res); + + assertContains(log, testOut.toString(), VisorConsistencyStatusTask.NOTHING_FOUND); + assertNotContains(log, testOut.toString(), "Status"); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java index ed32121..8507b57 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java @@ -30,6 +30,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.LongAdder; import java.util.function.Supplier; import javax.cache.Cache; import javax.cache.processor.EntryProcessor; @@ -1444,7 +1445,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager protected final PartitionUpdateCounter pCntr; /** Partition size. */ - private final AtomicLong storageSize = new AtomicLong(); + private final LongAdder storageSize = new LongAdder(); /** */ private final IntMap<AtomicLong> cacheSizes = new IntRWHashMap<>(); @@ -1551,7 +1552,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager return size != null ? (int)size.get() : 0; } - return storageSize.get(); + return storageSize.sum(); } /** {@inheritDoc} */ @@ -1568,7 +1569,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager /** {@inheritDoc} */ @Override public long fullSize() { - return storageSize.get(); + return storageSize.sum(); } /** @@ -1580,7 +1581,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager * TODO https://issues.apache.org/jira/browse/IGNITE-10082 * Using of counters is cheaper than tree operations. Return size checking after the ticked is resolved. */ - return grp.mvccEnabled() ? dataTree.isEmpty() : storageSize.get() == 0; + return grp.mvccEnabled() ? dataTree.isEmpty() : storageSize.sum() == 0; } catch (IgniteCheckedException e) { U.error(grp.shared().logger(IgniteCacheOffheapManagerImpl.class), "Failed to perform operation.", e); @@ -1591,7 +1592,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager /** {@inheritDoc} */ @Override public void updateSize(int cacheId, long delta) { - storageSize.addAndGet(delta); + storageSize.add(delta); if (grp.sharedGroup()) { AtomicLong size = cacheSizes.get(cacheId); @@ -3069,7 +3070,8 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager public void restoreState(long size, long updCntr, @Nullable Map<Integer, Long> cacheSizes, byte[] cntrUpdData) { pCntr.init(updCntr, cntrUpdData); - storageSize.set(size); + storageSize.reset(); + storageSize.add(size); if (cacheSizes != null) { for (Map.Entry<Integer, Long> e : cacheSizes.entrySet()) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/AbstractConsistencyTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/AbstractConsistencyTask.java new file mode 100644 index 0000000..20dc406 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/AbstractConsistencyTask.java @@ -0,0 +1,64 @@ +/* + * 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.visor.consistency; + +import java.util.List; +import org.apache.ignite.IgniteException; +import org.apache.ignite.compute.ComputeJobResult; +import org.apache.ignite.internal.util.typedef.X; +import org.apache.ignite.internal.visor.VisorMultiNodeTask; + +/** + * Base class for Consistency tasks. + * + * @param <A> Task argument type. + * @param <J> Job result type + */ +public abstract class AbstractConsistencyTask<A, J> extends VisorMultiNodeTask<A, VisorConsistencyTaskResult, J> { + /** {@inheritDoc} */ + @Override protected VisorConsistencyTaskResult reduce0(List<ComputeJobResult> results) throws IgniteException { + VisorConsistencyTaskResult taskRes = new VisorConsistencyTaskResult(); + StringBuilder sb = new StringBuilder(); + + for (ComputeJobResult res : results) { + if (res.isCancelled()) + taskRes.cancelled(true); + + Exception e = res.getException(); + + if (e != null) { + taskRes.failed(true); + + sb.append("Node: ").append(res.getNode()).append("\n") + .append(" Exception: ").append(e).append("\n") + .append(X.getFullStackTrace(e)).append("\n"); + } + + String data = res.getData(); + + if (data != null) + sb.append("Node: ").append(res.getNode()).append("\n") + .append(" Result: ").append(data).append("\n"); + } + + if (sb.length() != 0) + taskRes.message(sb.toString()); + + return taskRes; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTask.java index 47f6eae..1380bee 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTask.java @@ -18,7 +18,6 @@ package org.apache.ignite.internal.visor.consistency; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import javax.cache.CacheException; @@ -27,7 +26,6 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cluster.ClusterNode; -import org.apache.ignite.compute.ComputeJobResult; import org.apache.ignite.events.CacheConsistencyViolationEvent; import org.apache.ignite.internal.processors.cache.CacheGroupContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; @@ -37,9 +35,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.consistency. import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.util.GridConcurrentHashSet; import org.apache.ignite.internal.util.lang.GridCursor; -import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.visor.VisorJob; -import org.apache.ignite.internal.visor.VisorMultiNodeTask; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.resources.LoggerResource; @@ -48,8 +44,7 @@ import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION; /** * */ -public class VisorConsistencyRepairTask extends - VisorMultiNodeTask<VisorConsistencyRepairTaskArg, VisorConsistencyRepairTaskResult, String> { +public class VisorConsistencyRepairTask extends AbstractConsistencyTask<VisorConsistencyRepairTaskArg, String> { /** Serial version uid. */ private static final long serialVersionUID = 0L; @@ -67,37 +62,6 @@ public class VisorConsistencyRepairTask extends return new VisorConsistencyRepairJob(arg, debug); } - /** {@inheritDoc} */ - @Override protected VisorConsistencyRepairTaskResult reduce0(List<ComputeJobResult> results) throws IgniteException { - VisorConsistencyRepairTaskResult taskRes = new VisorConsistencyRepairTaskResult(); - StringBuilder sb = new StringBuilder(); - - for (ComputeJobResult res : results) { - if (res.isCancelled()) - taskRes.cancelled(true); - - Exception e = res.getException(); - - if (e != null) { - taskRes.failed(true); - - sb.append("Node: ").append(res.getNode()).append("\n") - .append(" Exception: ").append(e).append("\n") - .append(X.getFullStackTrace(e)).append("\n"); - } - - String data = res.getData(); - - if (data != null) - sb.append("Node: ").append(res.getNode()).append("\n") - .append(" Result: ").append(data).append("\n\n"); - } - - taskRes.message(sb.toString()); - - return taskRes; - } - /** * */ @@ -149,6 +113,8 @@ public class VisorConsistencyRepairTask extends log.info("Consistency check started [grp=" + grpCtx.cacheOrGroupName() + ", part=" + p + "]"); + VisorConsistencyStatusTask.MAP.put(arg, "0/" + part.fullSize()); + long cnt = 0; long statusTs = 0; @@ -198,6 +164,8 @@ public class VisorConsistencyRepairTask extends log.info("Consistency check progress [grp=" + grpCtx.cacheOrGroupName() + ", part=" + p + ", checked=" + cnt + "/" + part.fullSize() + "]"); + + VisorConsistencyStatusTask.MAP.put(arg, cnt + "/" + part.fullSize()); } } @@ -212,12 +180,14 @@ public class VisorConsistencyRepairTask extends } finally { part.release(); + + VisorConsistencyStatusTask.MAP.remove(arg); } if (!evts.isEmpty()) return processEvents(cctx, p, cnt); else - return NOTHING_FOUND + " [processed=" + cnt + "]"; + return NOTHING_FOUND + " [processed=" + cnt + "]\n"; } /** @@ -266,7 +236,7 @@ public class VisorConsistencyRepairTask extends return CONSISTENCY_VIOLATIONS_FOUND + " [found=" + found + ", fixed=" + fixed + ", processed=" + cnt + "]"; } else - return NOTHING_FOUND + " [processed=" + cnt + "]"; + return NOTHING_FOUND + " [processed=" + cnt + "]\n"; } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskArg.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskArg.java index ffcbf4e..134cda2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskArg.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskArg.java @@ -20,6 +20,7 @@ package org.apache.ignite.internal.visor.consistency; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.util.Objects; import org.apache.ignite.internal.dto.IgniteDataTransferObject; import org.apache.ignite.internal.util.typedef.internal.U; @@ -77,4 +78,22 @@ public class VisorConsistencyRepairTaskArg extends IgniteDataTransferObject { public int part() { return part; } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + VisorConsistencyRepairTaskArg arg = (VisorConsistencyRepairTaskArg)o; + + return part == arg.part && Objects.equals(cacheName, arg.cacheName); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(cacheName, part); + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyStatusTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyStatusTask.java new file mode 100644 index 0000000..af001e6 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyStatusTask.java @@ -0,0 +1,95 @@ +/* + * 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.visor.consistency; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.compute.ComputeJobResult; +import org.apache.ignite.internal.visor.VisorJob; +import org.apache.ignite.resources.LoggerResource; + +/** + * + */ +public class VisorConsistencyStatusTask extends AbstractConsistencyTask<Void, String> { + /** Serial version uid. */ + private static final long serialVersionUID = 0L; + + /** Nothing found. */ + public static final String NOTHING_FOUND = "Consistency check/repair operations were NOT found."; + + /** Status map. */ + public static final ConcurrentHashMap<VisorConsistencyRepairTaskArg, String> MAP = new ConcurrentHashMap<>(); + + /** {@inheritDoc} */ + @Override protected VisorJob<Void, String> job(Void arg) { + return new VisorConsistencyStatusJob(arg, debug); + } + + /** {@inheritDoc} */ + @Override protected VisorConsistencyTaskResult reduce0(List<ComputeJobResult> results) throws IgniteException { + VisorConsistencyTaskResult taskRes = super.reduce0(results); + + if (taskRes.message() == null) + taskRes.message(NOTHING_FOUND); + + return taskRes; + } + + /** + * + */ + private static class VisorConsistencyStatusJob extends VisorJob<Void, String> { + /** Serial version uid. */ + private static final long serialVersionUID = 0L; + + /** Injected logger. */ + @LoggerResource + protected IgniteLogger log; + + /** + * @param arg Arguments. + * @param debug Debug. + */ + protected VisorConsistencyStatusJob(Void arg, boolean debug) { + super(arg, debug); + } + + /** {@inheritDoc} */ + @Override protected String run(Void arg) throws IgniteException { + if (MAP.isEmpty()) + return null; + + StringBuilder sb = new StringBuilder(); + + for (Map.Entry<VisorConsistencyRepairTaskArg, String> entry : MAP.entrySet()) { + VisorConsistencyRepairTaskArg args = entry.getKey(); + String status = entry.getValue(); + + sb.append("\n Cache: ").append(args.cacheName()).append("\n") + .append(" Partition: ").append(args.part()).append("\n") + .append(" Status: ").append(status).append("\n"); + } + + return sb.toString(); + } + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskResult.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyTaskResult.java similarity index 96% rename from modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskResult.java rename to modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyTaskResult.java index 51e6d64..6c0eb21 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyRepairTaskResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/consistency/VisorConsistencyTaskResult.java @@ -26,7 +26,7 @@ import org.apache.ignite.internal.util.typedef.internal.U; /** * */ -public class VisorConsistencyRepairTaskResult extends IgniteDataTransferObject { +public class VisorConsistencyTaskResult extends IgniteDataTransferObject { /** */ private static final long serialVersionUID = 0L; diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties index 1bb7a46..8ed15fc 100644 --- a/modules/core/src/main/resources/META-INF/classnames.properties +++ b/modules/core/src/main/resources/META-INF/classnames.properties @@ -2010,7 +2010,7 @@ org.apache.ignite.internal.visor.baseline.VisorBaselineTaskResult org.apache.ignite.internal.visor.baseline.VisorBaselineViewTask org.apache.ignite.internal.visor.baseline.VisorBaselineViewTask$VisorBaselineViewJob org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskArg -org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskResult +org.apache.ignite.internal.visor.consistency.VisorConsistencyTaskResult org.apache.ignite.internal.visor.misc.VisorIdAndTagViewTaskResult org.apache.ignite.internal.visor.misc.VisorClusterChangeTagTaskResult org.apache.ignite.internal.visor.shutdown.VisorShutdownPolicyTask diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output index e7ad1e6..6a0ca41 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassTest_help.output @@ -309,6 +309,10 @@ If the file name isn't specified the output file name is: '<typeId>.bin' cache-name - Cache to be checked/repaired. partition - Cache's partition to be checked/repaired. + [EXPERIMENTAL] + Cache consistency check/repair operations status: + control.(sh|bat) --consistency status + By default commands affecting the cluster require interactive confirmation. Use --yes option to disable it. diff --git a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output index e7ad1e6..6a0ca41 100644 --- a/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output +++ b/modules/core/src/test/resources/org.apache.ignite.util/GridCommandHandlerClusterByClassWithSSLTest_help.output @@ -309,6 +309,10 @@ If the file name isn't specified the output file name is: '<typeId>.bin' cache-name - Cache to be checked/repaired. partition - Cache's partition to be checked/repaired. + [EXPERIMENTAL] + Cache consistency check/repair operations status: + control.(sh|bat) --consistency status + By default commands affecting the cluster require interactive confirmation. Use --yes option to disable it.