You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by mm...@apache.org on 2020/05/27 18:42:16 UTC
[ignite] branch master updated: IGNITE-12978: Add cancel snapshot
command (#7827)
This is an automated email from the ASF dual-hosted git repository.
mmuzaf 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 9d2824d IGNITE-12978: Add cancel snapshot command (#7827)
9d2824d is described below
commit 9d2824dd81e14c01a4e325e2ffe28f2608e2826e
Author: Maxim Muzafarov <mm...@apache.org>
AuthorDate: Wed May 27 21:41:52 2020 +0300
IGNITE-12978: Add cancel snapshot command (#7827)
---
.../java/org/apache/ignite/IgniteSnapshot.java | 9 ++
.../ignite/internal/MarshallerContextImpl.java | 27 ++--
.../internal/commandline/query/KillCommand.java | 22 +++-
.../internal/commandline/query/KillSubcommand.java | 5 +
.../commandline/snapshot/SnapshotCommand.java | 25 +++-
.../commandline/snapshot/SnapshotSubcommand.java | 5 +-
.../binary/CacheObjectBinaryProcessorImpl.java | 29 +++--
.../snapshot/IgniteSnapshotManager.java | 144 ++++++++++++++++++---
.../persistence/snapshot/SnapshotFutureTask.java | 8 +-
.../persistence/snapshot/SnapshotMXBeanImpl.java | 5 +
.../visor/snapshot/VisorSnapshotCancelTask.java | 62 +++++++++
.../org/apache/ignite/mxbean/SnapshotMXBean.java | 10 +-
.../main/resources/META-INF/classnames.properties | 2 +
.../snapshot/AbstractSnapshotSelfTest.java | 84 ++++++++++--
.../snapshot/IgniteClusterSnapshotSelfTest.java | 32 ++++-
.../snapshot/IgniteSnapshotMXBeanTest.java | 17 +++
.../snapshot/IgniteSnapshotManagerSelfTest.java | 6 +-
.../junits/common/GridCommonAbstractTest.java | 2 +
.../apache/ignite/util/GridCommandHandlerTest.java | 20 ++-
...ridCommandHandlerClusterByClassTest_help.output | 12 ++
...andHandlerClusterByClassWithSSLTest_help.output | 12 ++
.../IgniteClusterSnapshotWithIndexesTest.java | 15 +--
.../processors/query/SqlSystemViewsSelfTest.java | 20 +--
.../ignite/util/KillCommandsCommandShTest.java | 26 +++-
.../apache/ignite/util/KillCommandsMXBeanTest.java | 51 +++++++-
.../apache/ignite/util/KillCommandsSQLTest.java | 5 +-
.../org/apache/ignite/util/KillCommandsTests.java | 6 +-
27 files changed, 562 insertions(+), 99 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSnapshot.java b/modules/core/src/main/java/org/apache/ignite/IgniteSnapshot.java
index 753d427..3623c1f 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSnapshot.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSnapshot.java
@@ -39,4 +39,13 @@ public interface IgniteSnapshot {
* @return Future which will be completed when a process ends.
*/
public IgniteFuture<Void> createSnapshot(String name);
+
+ /**
+ * Cancel running snapshot operation. All intermediate results of cancelled snapshot operation will be deleted.
+ * If snapshot already created this command will have no effect.
+ *
+ * @param name Snapshot name to cancel.
+ * @return Future which will be completed when cancel operation finished.
+ */
+ public IgniteFuture<Void> cancelSnapshot(String name);
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
index 2897291..a690075 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerContextImpl.java
@@ -191,7 +191,7 @@ public class MarshallerContextImpl implements MarshallerContext {
*/
public static void saveMappings(GridKernalContext ctx, List<Map<Integer, MappedName>> mappings, File dir) {
MarshallerMappingFileStore writer = new MarshallerMappingFileStore(ctx,
- mappingFileStoreWorkDir(dir.getAbsolutePath()));
+ resolveMappingFileStoreWorkDir(dir.getAbsolutePath()));
addPlatformMappings(ctx.log(MarshallerContextImpl.class),
mappings,
@@ -592,7 +592,7 @@ public class MarshallerContextImpl implements MarshallerContext {
String workDir = U.workDirectory(cfg.getWorkDirectory(), cfg.getIgniteHome());
fileStore = marshallerMappingFileStoreDir == null ?
- new MarshallerMappingFileStore(ctx, mappingFileStoreWorkDir(workDir)) :
+ new MarshallerMappingFileStore(ctx, resolveMappingFileStoreWorkDir(workDir)) :
new MarshallerMappingFileStore(ctx, marshallerMappingFileStoreDir);
this.transport = transport;
@@ -607,13 +607,24 @@ public class MarshallerContextImpl implements MarshallerContext {
* @param igniteWorkDir Base ignite working directory.
* @return Resolved directory.
*/
+ public static File resolveMappingFileStoreWorkDir(String igniteWorkDir) {
+ File dir = mappingFileStoreWorkDir(igniteWorkDir);
+
+ if (!U.mkdirs(dir))
+ throw new IgniteException("Could not create directory for marshaller mappings: " + dir);
+
+ return dir;
+ }
+
+ /**
+ * @param igniteWorkDir Base ignite working directory.
+ * @return Work directory for marshaller mappings.
+ */
public static File mappingFileStoreWorkDir(String igniteWorkDir) {
- try {
- return U.resolveWorkDirectory(igniteWorkDir, "marshaller", false);
- }
- catch (IgniteCheckedException e) {
- throw new IgniteException(e);
- }
+ if (F.isEmpty(igniteWorkDir))
+ throw new IgniteException("Work directory has not been set: " + igniteWorkDir);
+
+ return new File(igniteWorkDir, "marshaller");
}
/**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillCommand.java
index 18d024e..38b170d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillCommand.java
@@ -27,6 +27,8 @@ 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.util.typedef.T2;
+import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTask;
+import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTaskArg;
import org.apache.ignite.internal.visor.query.VisorContinuousQueryCancelTask;
import org.apache.ignite.internal.visor.query.VisorContinuousQueryCancelTaskArg;
import org.apache.ignite.internal.visor.query.VisorQueryCancelOnInitiatorTask;
@@ -35,25 +37,25 @@ import org.apache.ignite.internal.visor.query.VisorScanQueryCancelTask;
import org.apache.ignite.internal.visor.query.VisorScanQueryCancelTaskArg;
import org.apache.ignite.internal.visor.service.VisorCancelServiceTask;
import org.apache.ignite.internal.visor.service.VisorCancelServiceTaskArg;
-import org.apache.ignite.mxbean.QueryMXBean;
-import org.apache.ignite.mxbean.ServiceMXBean;
-import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTask;
-import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTaskArg;
+import org.apache.ignite.internal.visor.snapshot.VisorSnapshotCancelTask;
import org.apache.ignite.internal.visor.tx.VisorTxOperation;
import org.apache.ignite.internal.visor.tx.VisorTxTask;
import org.apache.ignite.internal.visor.tx.VisorTxTaskArg;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.mxbean.ComputeMXBean;
+import org.apache.ignite.mxbean.QueryMXBean;
+import org.apache.ignite.mxbean.ServiceMXBean;
import org.apache.ignite.mxbean.TransactionsMXBean;
import static java.util.Collections.singletonMap;
import static org.apache.ignite.internal.QueryMXBeanImpl.EXPECTED_GLOBAL_QRY_ID_FORMAT;
import static org.apache.ignite.internal.commandline.CommandList.KILL;
import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode;
+import static org.apache.ignite.internal.commandline.query.KillSubcommand.COMPUTE;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.CONTINUOUS;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.SCAN;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.SERVICE;
-import static org.apache.ignite.internal.commandline.query.KillSubcommand.COMPUTE;
+import static org.apache.ignite.internal.commandline.query.KillSubcommand.SNAPSHOT;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.SQL;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.TRANSACTION;
import static org.apache.ignite.internal.sql.command.SqlKillQueryCommand.parseGlobalQueryId;
@@ -171,6 +173,13 @@ public class KillCommand implements Command<Object> {
break;
+ case SNAPSHOT:
+ taskArgs = argIter.nextArg("Expected snapshot name.");
+
+ taskName = VisorSnapshotCancelTask.class.getName();
+
+ break;
+
default:
throw new IllegalArgumentException("Unknown kill subcommand: " + cmd);
}
@@ -205,6 +214,9 @@ public class KillCommand implements Command<Object> {
Command.usage(log, "Kill continuous query by routine id:", KILL, params, CONTINUOUS.toString(),
"origin_node_id", "routine_id");
+
+ Command.usage(log, "Kill running snapshot by snapshot name:", KILL, singletonMap("snapshot_name", "Snapshot name."),
+ SNAPSHOT.toString(), "snapshot_name");
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillSubcommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillSubcommand.java
index aa50575..311ab96 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillSubcommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/query/KillSubcommand.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.commandline.query;
import org.apache.ignite.mxbean.ComputeMXBean;
import org.apache.ignite.mxbean.QueryMXBean;
import org.apache.ignite.mxbean.ServiceMXBean;
+import org.apache.ignite.mxbean.SnapshotMXBean;
import org.apache.ignite.mxbean.TransactionsMXBean;
/**
@@ -30,6 +31,7 @@ import org.apache.ignite.mxbean.TransactionsMXBean;
* @see ComputeMXBean
* @see TransactionsMXBean
* @see ServiceMXBean
+ * @see SnapshotMXBean
*/
public enum KillSubcommand {
/** Kill compute task. */
@@ -49,4 +51,7 @@ public enum KillSubcommand {
/** Kill continuous query. */
CONTINUOUS,
+
+ /** Kill snapshot operation. */
+ SNAPSHOT,
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotCommand.java
index 7804524..2c77e69 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotCommand.java
@@ -24,12 +24,14 @@ 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.processors.cache.persistence.snapshot.IgniteSnapshotManager;
+import org.apache.ignite.internal.visor.snapshot.VisorSnapshotCancelTask;
import org.apache.ignite.internal.visor.snapshot.VisorSnapshotCreateTask;
import org.apache.ignite.mxbean.SnapshotMXBean;
import static java.util.Collections.singletonMap;
import static org.apache.ignite.internal.commandline.CommandList.SNAPSHOT;
import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode;
+import static org.apache.ignite.internal.commandline.snapshot.SnapshotSubcommand.CANCEL;
import static org.apache.ignite.internal.commandline.snapshot.SnapshotSubcommand.CREATE;
import static org.apache.ignite.internal.commandline.snapshot.SnapshotSubcommand.of;
@@ -77,20 +79,31 @@ public class SnapshotCommand implements Command<Object> {
if (cmd == null)
throw new IllegalArgumentException("Expected correct action.");
- if (cmd == CREATE) {
- String name = argIter.nextArg("Expected snapshot name.");
+ switch (cmd) {
+ case CREATE:
+ taskName = VisorSnapshotCreateTask.class.getName();
+ taskArgs = argIter.nextArg("Expected snapshot name.");
- taskName = VisorSnapshotCreateTask.class.getName();
- taskArgs = name;
+ break;
+
+ case CANCEL:
+ taskName = VisorSnapshotCancelTask.class.getName();
+ taskArgs = argIter.nextArg("Expected snapshot name.");
+
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown snapshot sub-command: " + cmd);
}
- else
- throw new IllegalArgumentException("Unknown snapshot sub-command: " + cmd);
}
/** {@inheritDoc} */
@Override public void printUsage(Logger log) {
Command.usage(log, "Create cluster snapshot:", SNAPSHOT, singletonMap("snapshot_name", "Snapshot name."),
CREATE.toString(), "snapshot_name");
+
+ Command.usage(log, "Cancel running snapshot:", SNAPSHOT, singletonMap("snapshot_name", "Snapshot name."),
+ CANCEL.toString(), "snapshot_name");
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotSubcommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotSubcommand.java
index 7c206ad..0d365fa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotSubcommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/snapshot/SnapshotSubcommand.java
@@ -26,7 +26,10 @@ import org.jetbrains.annotations.Nullable;
*/
public enum SnapshotSubcommand {
/** Sub-command to create a cluster snapshot. */
- CREATE("create");
+ CREATE("create"),
+
+ /** Sub-command to cancel running snapshot. */
+ CANCEL("cancel");
/** Sub-command name. */
private final String name;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index f114bf7..3fab2ac 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -21,6 +21,7 @@ import java.io.File;
import java.io.Serializable;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -210,20 +211,26 @@ public class CacheObjectBinaryProcessorImpl extends GridProcessorAdapter impleme
* @return Working directory.
*/
public static File resolveBinaryWorkDir(String igniteWorkDir, String consId) {
- try {
- File workDir = new File(U.resolveWorkDirectory(
- igniteWorkDir,
- BINARY_META_FOLDER,
- false),
- consId);
+ File workDir = binaryWorkDir(igniteWorkDir, consId);
- U.ensureDirectory(workDir, "directory for serialized binary metadata", null);
+ if (!U.mkdirs(workDir))
+ throw new IgniteException("Could not create directory for binary metadata: " + workDir);
- return workDir;
- }
- catch (IgniteCheckedException e) {
- throw new IgniteException(e);
+ return workDir;
+ }
+
+ /**
+ * @param igniteWorkDir Basic ignite working directory.
+ * @param consId Node consistent id.
+ * @return Working directory.
+ */
+ public static File binaryWorkDir(String igniteWorkDir, String consId) {
+ if (F.isEmpty(igniteWorkDir) || F.isEmpty(consId)) {
+ throw new IgniteException("Work directory or consistent id has not been set " +
+ "[igniteWorkDir=" + igniteWorkDir + ", consId=" + consId + ']');
}
+
+ return Paths.get(igniteWorkDir, BINARY_META_FOLDER, consId).toFile();
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
index a1fdf11..18ac4bc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManager.java
@@ -58,6 +58,7 @@ import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteFeatures;
+import org.apache.ignite.internal.IgniteFutureCancelledCheckedException;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.NodeStoppingException;
import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
@@ -96,6 +97,7 @@ import org.apache.ignite.internal.util.future.IgniteFinishedFutureImpl;
import org.apache.ignite.internal.util.future.IgniteFutureImpl;
import org.apache.ignite.internal.util.lang.GridClosureException;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.CX1;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -119,7 +121,7 @@ import static org.apache.ignite.internal.events.DiscoveryCustomEvent.EVT_DISCOVE
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL;
import static org.apache.ignite.internal.pagemem.PageIdAllocator.INDEX_PARTITION;
import static org.apache.ignite.internal.pagemem.PageIdAllocator.MAX_PARTITION_ID;
-import static org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl.resolveBinaryWorkDir;
+import static org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl.binaryWorkDir;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.INDEX_FILE_NAME;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.PART_FILE_TEMPLATE;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.getPartitionFile;
@@ -390,18 +392,18 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
* @param snpDir Snapshot dir.
* @param folderName Local node folder name (see {@link U#maskForFileName} with consistent id).
*/
- public static void deleteSnapshot(File snpDir, String folderName) {
+ public void deleteSnapshot(File snpDir, String folderName) {
if (!snpDir.exists())
return;
assert snpDir.isDirectory() : snpDir;
try {
- File binDir = resolveBinaryWorkDir(snpDir.getAbsolutePath(), folderName);
- File dbDir = U.resolveWorkDirectory(snpDir.getAbsolutePath(), databaseRelativePath(folderName), false);
+ File binDir = binaryWorkDir(snpDir.getAbsolutePath(), folderName);
+ File nodeDbDir = new File(snpDir.getAbsolutePath(), databaseRelativePath(folderName));
U.delete(binDir);
- U.delete(dbDir);
+ U.delete(nodeDbDir);
File marshDir = mappingFileStoreWorkDir(snpDir.getAbsolutePath());
@@ -417,14 +419,26 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
// Skip files which can be concurrently removed from FileTree.
return FileVisitResult.CONTINUE;
}
+
+ @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+ dir.toFile().delete();
+
+ if (log.isInfoEnabled() && exc != null)
+ log.info("Marshaller directory cleaned with an exception: " + exc.getMessage());
+
+ return FileVisitResult.CONTINUE;
+ }
});
File db = new File(snpDir, DB_DEFAULT_FOLDER);
- if (!db.exists() || db.list().length == 0)
+ if (!db.exists() || db.list() == null || db.list().length == 0) {
+ marshDir.delete();
+ db.delete();
U.delete(snpDir);
+ }
}
- catch (IOException | IgniteCheckedException e) {
+ catch (IOException e) {
throw new IgniteException(e);
}
}
@@ -522,11 +536,18 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
SnapshotOperationRequest snpReq = clusterSnpReq;
+ boolean cancelled = err.values().stream().anyMatch(e -> e instanceof IgniteFutureCancelledCheckedException);
+
if (snpReq == null || !snpReq.rqId.equals(id)) {
synchronized (snpOpMux) {
if (clusterSnpFut != null && clusterSnpFut.rqId.equals(id)) {
- clusterSnpFut.onDone(new IgniteCheckedException("Snapshot operation has not been fully completed " +
- "[err=" + err + ", snpReq=" + snpReq + ']'));
+ if (cancelled) {
+ clusterSnpFut.onDone(new IgniteFutureCancelledCheckedException("Execution of snapshot tasks " +
+ "has been cancelled by external process [err=" + err + ", snpReq=" + snpReq + ']'));
+ } else {
+ clusterSnpFut.onDone(new IgniteCheckedException("Snapshot operation has not been fully completed " +
+ "[err=" + err + ", snpReq=" + snpReq + ']'));
+ }
clusterSnpFut = null;
}
@@ -540,10 +561,12 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
missed.removeAll(res.keySet());
missed.removeAll(err.keySet());
- snpReq.hasErr = !F.isEmpty(err) || !missed.isEmpty();
-
- if (snpReq.hasErr) {
- U.warn(log, "Execution of local snapshot tasks fails or them haven't been executed " +
+ if (cancelled) {
+ snpReq.err = new IgniteFutureCancelledCheckedException("Execution of snapshot tasks " +
+ "has been cancelled by external process [err=" + err + ", missed=" + missed + ']');
+ }
+ else if (!F.isEmpty(err) || !missed.isEmpty()) {
+ snpReq.err = new IgniteCheckedException("Execution of local snapshot tasks fails or them haven't been executed " +
"due to some of nodes left the cluster. Uncompleted snapshot will be deleted " +
"[err=" + err + ", missed=" + missed + ']');
}
@@ -561,7 +584,7 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
return new GridFinishedFuture<>(new SnapshotOperationResponse());
try {
- if (req.hasErr)
+ if (req.err != null)
deleteSnapshot(snapshotLocalDir(req.snpName), pdsSettings.folderName());
removeLastMetaStorageKey();
@@ -591,17 +614,19 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
synchronized (snpOpMux) {
if (clusterSnpFut != null) {
- if (endFail.isEmpty() && !snpReq.hasErr) {
+ if (endFail.isEmpty() && snpReq.err == null) {
clusterSnpFut.onDone();
if (log.isInfoEnabled())
log.info("Cluster-wide snapshot operation finished successfully [req=" + snpReq + ']');
}
- else {
+ else if (snpReq.err == null) {
clusterSnpFut.onDone(new IgniteCheckedException("Snapshot creation has been finished with an error. " +
"Local snapshot tasks may not finished completely or finalizing results fails " +
- "[hasErr=" + snpReq.hasErr + ", fail=" + endFail + ", err=" + err + ']'));
+ "[fail=" + endFail + ", err=" + err + ']'));
}
+ else
+ clusterSnpFut.onDone(snpReq.err);
clusterSnpFut = null;
}
@@ -635,6 +660,66 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
}
/** {@inheritDoc} */
+ @Override public IgniteFuture<Void> cancelSnapshot(String name) {
+ A.notNullOrEmpty(name, "Snapshot name must be not empty or null");
+
+ IgniteInternalFuture<Void> fut0 = cctx.kernalContext().closure()
+ .broadcast(new CancelSnapshotClosure(),
+ name,
+ cctx.discovery().aliveServerNodes(),
+ null)
+ .chain(new CX1<IgniteInternalFuture<Collection<Void>>, Void>() {
+ @Override public Void applyx(IgniteInternalFuture<Collection<Void>> f) throws IgniteCheckedException {
+ f.get();
+
+ return null;
+ }
+ });
+
+ return new IgniteFutureImpl<>(fut0);
+ }
+
+ /**
+ * @param name Snapshot name to cancel operation on local node.
+ */
+ public void cancelLocalSnapshotTask(String name) {
+ A.notNullOrEmpty(name, "Snapshot name must be not null or empty");
+
+ ClusterSnapshotFuture fut0 = null;
+
+ busyLock.enterBusy();
+
+ try {
+ for (SnapshotFutureTask sctx : locSnpTasks.values()) {
+ if (sctx.snapshotName().equals(name))
+ sctx.cancel();
+ }
+
+ synchronized (snpOpMux) {
+ if (clusterSnpFut != null)
+ fut0 = clusterSnpFut;
+ }
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+
+ // Future may be completed with cancelled exception, which is expected.
+ try {
+ if (fut0 != null)
+ fut0.get();
+ }
+ catch (IgniteCheckedException e) {
+ if (e instanceof IgniteFutureCancelledCheckedException) {
+ if (log.isInfoEnabled())
+ log.info("Expected cancelled exception: " + e.getMessage());
+ }
+ else
+ throw new IgniteException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteFuture<Void> createSnapshot(String name) {
A.notNullOrEmpty(name, "Snapshot name cannot be null or empty.");
A.ensure(U.alphanumericUnderscore(name), "Snapshot name must satisfy the following name pattern: a-zA-Z0-9_");
@@ -1105,7 +1190,8 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
else {
deleteSnapshot(snpLocDir, pdsSettings.folderName());
- U.warn(log, "Local snapshot sender closed due to an error occurred", th);
+ if (log.isDebugEnabled())
+ log.debug("Local snapshot sender closed due to an error occurred: " + th.getMessage());
}
}
}
@@ -1132,8 +1218,8 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
@GridToStringInclude
private final Set<UUID> bltNodes;
- /** {@code true} if an execution of local snapshot tasks failed with an error. */
- private volatile boolean hasErr;
+ /** Exception occurred during snapshot operation processing. */
+ private volatile IgniteCheckedException err;
/**
* @param snpName Snapshot name.
@@ -1266,6 +1352,24 @@ public class IgniteSnapshotManager extends GridCacheSharedManagerAdapter
}
}
+ /** Cancel snapshot operation closure. */
+ @GridInternal
+ private static class CancelSnapshotClosure implements IgniteClosure<String, Void> {
+ /** Serial version uid. */
+ private static final long serialVersionUID = 0L;
+
+ /** Auto-injected grid instance. */
+ @IgniteInstanceResource
+ private transient IgniteEx ignite;
+
+ /** {@inheritDoc} */
+ @Override public Void apply(String snpName) {
+ ignite.context().cache().context().snapshotMgr().cancelLocalSnapshotTask(snpName);
+
+ return null;
+ }
+ }
+
/** Wrapper of internal checked exceptions. */
private static class IgniteSnapshotFutureImpl extends IgniteFutureImpl<Void> {
/** @param fut Internal future. */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotFutureTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotFutureTask.java
index 93270e2..04c1962 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotFutureTask.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotFutureTask.java
@@ -49,6 +49,7 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.binary.BinaryType;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteFutureCancelledCheckedException;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.store.PageStore;
import org.apache.ignite.internal.pagemem.store.PageWriteListener;
@@ -262,7 +263,8 @@ class SnapshotFutureTask extends GridFutureAdapter<Boolean> implements DbCheckpo
startedFut.onDone(th);
- U.warn(log, "Snapshot task has accepted exception to stop: " + th);
+ if (!(th instanceof IgniteFutureCancelledCheckedException))
+ U.error(log, "Snapshot task has accepted exception to stop", th);
}
/** {@inheritDoc} */
@@ -627,8 +629,8 @@ class SnapshotFutureTask extends GridFutureAdapter<Boolean> implements DbCheckpo
/** {@inheritDoc} */
@Override public boolean cancel() {
- acceptException(new IgniteCheckedException("Snapshot operation has been cancelled by external process " +
- "[snpName=" + snpName + ']'));
+ acceptException(new IgniteFutureCancelledCheckedException("Snapshot operation has been cancelled " +
+ "by external process [snpName=" + snpName + ']'));
try {
closeAsync().get();
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotMXBeanImpl.java
index c6b101a..9dc1361 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotMXBeanImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/SnapshotMXBeanImpl.java
@@ -42,4 +42,9 @@ public class SnapshotMXBeanImpl implements SnapshotMXBean {
if (fut.isDone())
fut.get();
}
+
+ /** {@inheritDoc} */
+ @Override public void cancelSnapshot(String snpName) {
+ mgr.cancelSnapshot(snpName).get();
+ }
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/snapshot/VisorSnapshotCancelTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/snapshot/VisorSnapshotCancelTask.java
new file mode 100644
index 0000000..b894e49
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/snapshot/VisorSnapshotCancelTask.java
@@ -0,0 +1,62 @@
+/*
+ * 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.snapshot;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteSnapshot;
+import org.apache.ignite.internal.commandline.snapshot.SnapshotCommand;
+import org.apache.ignite.internal.processors.cache.persistence.snapshot.SnapshotMXBeanImpl;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorOneNodeTask;
+
+/**
+ * @see SnapshotCommand
+ * @see IgniteSnapshot#cancelSnapshot(String)
+ */
+@GridInternal
+public class VisorSnapshotCancelTask extends VisorOneNodeTask<String, String> {
+ /** Serial version uid. */
+ private static final long serialVersionUID = 0L;
+
+ /** {@inheritDoc} */
+ @Override protected VisorJob<String, String> job(String arg) {
+ return new VisorSnapshotCancelJob(arg, debug);
+ }
+
+ /** */
+ private static class VisorSnapshotCancelJob extends VisorJob<String, String> {
+ /** Serial version uid. */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * @param name Snapshot name.
+ * @param debug Flag indicating whether debug information should be printed into node log.
+ */
+ protected VisorSnapshotCancelJob(String name, boolean debug) {
+ super(name, debug);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected String run(String name) throws IgniteException {
+ new SnapshotMXBeanImpl(ignite.context()).cancelSnapshot(name);
+
+ return "Snapshot operation cancelled.";
+ }
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/mxbean/SnapshotMXBean.java b/modules/core/src/main/java/org/apache/ignite/mxbean/SnapshotMXBean.java
index 22816d2..e6b42583 100644
--- a/modules/core/src/main/java/org/apache/ignite/mxbean/SnapshotMXBean.java
+++ b/modules/core/src/main/java/org/apache/ignite/mxbean/SnapshotMXBean.java
@@ -27,9 +27,17 @@ public interface SnapshotMXBean {
/**
* Create the cluster-wide snapshot with given name asynchronously.
*
- * @param snpName Snapshot name to created.
+ * @param snpName Snapshot name to be created.
* @see IgniteSnapshot#createSnapshot(String) (String)
*/
@MXBeanDescription("Create cluster-wide snapshot.")
public void createSnapshot(@MXBeanParameter(name = "snpName", description = "Snapshot name.") String snpName);
+
+ /**
+ * Cancel previously started snapshot operation on the node initiator.
+ *
+ * @param snpName Snapshot name to cancel.
+ */
+ @MXBeanDescription("Cancel started cluster-wide snapshot on the node initiator.")
+ public void cancelSnapshot(@MXBeanParameter(name = "snpName", description = "Snapshot name.") String snpName);
}
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties
index 90120c0..486b660 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -2338,6 +2338,8 @@ org.apache.ignite.internal.visor.service.VisorServiceTask
org.apache.ignite.internal.visor.service.VisorServiceTask$VisorServiceJob
org.apache.ignite.internal.visor.snapshot.VisorSnapshotCreateTask
org.apache.ignite.internal.visor.snapshot.VisorSnapshotCreateTask$VisorSnapshotCreateJob
+org.apache.ignite.internal.visor.snapshot.VisorSnapshotCancelTask
+org.apache.ignite.internal.visor.snapshot.VisorSnapshotCancelTask$VisorSnapshotCancelJob
org.apache.ignite.internal.visor.tx.FetchNearXidVersionTask
org.apache.ignite.internal.visor.tx.FetchNearXidVersionTask$FetchNearXidVersionJob
org.apache.ignite.internal.visor.tx.TxKeyLockType
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/AbstractSnapshotSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/AbstractSnapshotSelfTest.java
index 5d49f1b..44e8e78 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/AbstractSnapshotSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/AbstractSnapshotSelfTest.java
@@ -25,6 +25,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -34,6 +35,7 @@ import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -63,8 +65,11 @@ import org.apache.ignite.internal.processors.cache.persistence.partstate.GroupPa
import org.apache.ignite.internal.processors.cache.persistence.wal.crc.FastCrc;
import org.apache.ignite.internal.processors.marshaller.MappedName;
import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteFutureCancelledException;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
@@ -77,11 +82,12 @@ import org.junit.Before;
import static java.nio.file.Files.newDirectoryStream;
import static org.apache.ignite.cluster.ClusterState.ACTIVE;
import static org.apache.ignite.cluster.ClusterState.INACTIVE;
-import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_SNAPSHOT_DIRECTORY;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.FILE_SUFFIX;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.PART_FILE_PREFIX;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.DFLT_SNAPSHOT_TMP_DIR;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.resolveSnapshotWorkDirectory;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsAnyCause;
+import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
/**
* Base snapshot tests.
@@ -120,13 +126,6 @@ public abstract class AbstractSnapshotSelfTest extends GridCommonAbstractTest {
.setDiscoverySpi(discoSpi);
}
- /** {@inheritDoc} */
- @Override protected void cleanPersistenceDir() throws Exception {
- super.cleanPersistenceDir();
-
- U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_SNAPSHOT_DIRECTORY, false));
- }
-
/** @throws Exception If fails. */
@Before
public void beforeTestSnapshot() throws Exception {
@@ -358,6 +357,65 @@ public abstract class AbstractSnapshotSelfTest extends GridCommonAbstractTest {
}
/**
+ * @param grids Grids to block snapshot executors.
+ * @return Wrapped snapshot executor list.
+ */
+ protected static List<BlockingExecutor> setBlockingSnapshotExecutor(List<? extends Ignite> grids) {
+ List<BlockingExecutor> execs = new ArrayList<>();
+
+ for (Ignite grid : grids) {
+ IgniteSnapshotManager mgr = snp((IgniteEx)grid);
+ Function<String, SnapshotSender> old = mgr.localSnapshotSenderFactory();
+
+ BlockingExecutor block = new BlockingExecutor(mgr.snapshotExecutorService());
+ execs.add(block);
+
+ mgr.localSnapshotSenderFactory((snpName) ->
+ new DelegateSnapshotSender(log, block, old.apply(snpName)));
+ }
+
+ return execs;
+ }
+
+ /**
+ * @param startCli Client node to start snapshot.
+ * @param srvs Server nodes.
+ * @param cache Persisted cache.
+ * @param snpCanceller Snapshot cancel closure.
+ */
+ public static void doSnapshotCancellationTest(
+ IgniteEx startCli,
+ List<IgniteEx> srvs,
+ IgniteCache<?, ?> cache,
+ Consumer<String> snpCanceller
+ ) {
+ IgniteEx srv = srvs.get(0);
+
+ CacheConfiguration<?, ?> ccfg = cache.getConfiguration(CacheConfiguration.class);
+
+ assertTrue(CU.isPersistenceEnabled(srv.configuration()));
+ assertTrue(CU.isPersistentCache(ccfg, srv.configuration().getDataStorageConfiguration()));
+
+ File snpDir = resolveSnapshotWorkDirectory(srv.configuration());
+
+ List<BlockingExecutor> execs = setBlockingSnapshotExecutor(srvs);
+
+ IgniteFuture<Void> fut = startCli.snapshot().createSnapshot(SNAPSHOT_NAME);
+
+ for (BlockingExecutor exec : execs)
+ exec.waitForBlocked(30_000L);
+
+ snpCanceller.accept(SNAPSHOT_NAME);
+
+ assertThrowsAnyCause(log,
+ fut::get,
+ IgniteFutureCancelledException.class,
+ "Execution of snapshot tasks has been cancelled by external process");
+
+ assertEquals("Snapshot directory must be empty due to snapshot cancelled", 0, snpDir.list().length);
+ }
+
+ /**
* @param ignite Ignite instance to resolve discovery spi to.
* @return BlockingCustomMessageDiscoverySpi instance.
*/
@@ -538,6 +596,16 @@ public abstract class AbstractSnapshotSelfTest extends GridCommonAbstractTest {
delegate.execute(cmd);
}
+ /** @param timeout Timeout in milliseconds. */
+ public void waitForBlocked(long timeout) {
+ try {
+ assertTrue(waitForCondition(() -> !tasks.isEmpty(), timeout));
+ }
+ catch (IgniteInterruptedCheckedException e) {
+ throw new IgniteException(e);
+ }
+ }
+
/** Unblock and schedule tasks for execution. */
public void unblock() {
block = false;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotSelfTest.java
index f4c7fc7..34d0762 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotSelfTest.java
@@ -100,7 +100,7 @@ public class IgniteClusterSnapshotSelfTest extends AbstractSnapshotSelfTest {
private static final long REBALANCE_AWAIT_TIME = GridTestUtils.SF.applyLB(10_000, 3_000);
/** Cache configuration for test. */
- private static CacheConfiguration<Integer, Integer> atomicCcfg = new CacheConfiguration<Integer, Integer>("atomicCacheName")
+ private static final CacheConfiguration<Integer, Integer> atomicCcfg = new CacheConfiguration<Integer, Integer>("atomicCacheName")
.setAtomicityMode(CacheAtomicityMode.ATOMIC)
.setBackups(2)
.setAffinity(new RendezvousAffinityFunction(false, CACHE_PARTS_COUNT));
@@ -578,7 +578,7 @@ public class IgniteClusterSnapshotSelfTest extends AbstractSnapshotSelfTest {
assertThrowsAnyCause(log,
fut::get,
IgniteCheckedException.class,
- "Snapshot creation has been finished with an error");
+ "Execution of local snapshot tasks fails");
assertTrue("Snapshot directory must be empty for node 0 due to snapshot future fail: " + dirNameIgnite0,
!searchDirectoryRecursively(locSnpDir.toPath(), dirNameIgnite0).isPresent());
@@ -630,7 +630,7 @@ public class IgniteClusterSnapshotSelfTest extends AbstractSnapshotSelfTest {
assertThrowsAnyCause(log,
() -> ignite.snapshot().createSnapshot(SNAPSHOT_NAME).get(),
IgniteCheckedException.class,
- "Snapshot creation has been finished with an error");
+ "Execution of local snapshot tasks fails");
assertTrue("Snapshot directory must be empty: " + grid0Dir,
!searchDirectoryRecursively(locSnpDir.toPath(), grid0Dir).isPresent());
@@ -1101,6 +1101,32 @@ public class IgniteClusterSnapshotSelfTest extends AbstractSnapshotSelfTest {
"Client disconnected. Snapshot result is unknown");
}
+ /** @throws Exception If fails. */
+ @Test
+ public void testClusterSnapshotInProgressCancelled() throws Exception {
+ IgniteEx srv = startGridsWithCache(1, dfltCacheCfg, CACHE_KEYS_RANGE);
+ IgniteEx startCli = startClientGrid(1);
+ IgniteEx killCli = startClientGrid(2);
+
+ doSnapshotCancellationTest(startCli, Collections.singletonList(srv), srv.cache(dfltCacheCfg.getName()),
+ snpName -> killCli.snapshot().cancelSnapshot(snpName).get());
+ }
+
+ /** @throws Exception If fails. */
+ @Test
+ public void testClusterSnapshotFinishedTryCancel() throws Exception {
+ IgniteEx ignite = startGridsWithCache(2, dfltCacheCfg, CACHE_KEYS_RANGE);
+
+ ignite.snapshot().createSnapshot(SNAPSHOT_NAME).get();
+ ignite.snapshot().cancelSnapshot(SNAPSHOT_NAME).get();
+
+ stopAllGrids();
+
+ IgniteEx snpIg = startGridsFromSnapshot(2, SNAPSHOT_NAME);
+
+ assertSnapshotCacheKeys(snpIg.cache(dfltCacheCfg.getName()));
+ }
+
/**
* @param ignite Ignite instance.
* @param started Latch will be released when delta partition processing starts.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotMXBeanTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotMXBeanTest.java
index 0aaa789..c662a5a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotMXBeanTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotMXBeanTest.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.processors.cache.persistence.snapshot;
+import java.util.Collections;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.MBeanException;
@@ -64,6 +65,22 @@ public class IgniteSnapshotMXBeanTest extends AbstractSnapshotSelfTest {
assertSnapshotCacheKeys(snp.cache(dfltCacheCfg.getName()));
}
+ /** @throws Exception If fails. */
+ @Test
+ public void testCancelSnapshot() throws Exception {
+ IgniteEx srv = startGridsWithCache(1, dfltCacheCfg, CACHE_KEYS_RANGE);
+ IgniteEx startCli = startClientGrid(1);
+ IgniteEx killCli = startClientGrid(2);
+
+ SnapshotMXBean mxBean = getMxBean(killCli.name(), "Snapshot", SnapshotMXBeanImpl.class,
+ SnapshotMXBean.class);
+
+ doSnapshotCancellationTest(startCli,
+ Collections.singletonList(srv),
+ srv.cache(dfltCacheCfg.getName()),
+ mxBean::cancelSnapshot);
+ }
+
/**
* @param mBean Ignite snapshot MBean.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManagerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManagerSelfTest.java
index b957d48..6e29aa9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManagerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteSnapshotManagerSelfTest.java
@@ -60,7 +60,7 @@ import org.apache.ignite.testframework.GridTestUtils;
import org.junit.Test;
import static org.apache.ignite.internal.MarshallerContextImpl.mappingFileStoreWorkDir;
-import static org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl.resolveBinaryWorkDir;
+import static org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl.binaryWorkDir;
import static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.cacheDirName;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.CP_SNAPSHOT_REASON;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.databaseRelativePath;
@@ -110,9 +110,9 @@ public class IgniteSnapshotManagerSelfTest extends AbstractSnapshotSelfTest {
IgniteConfiguration cfg = ig.context().config();
PdsFolderSettings settings = ig.context().pdsFolderResolver().resolveFolders();
String nodePath = databaseRelativePath(settings.folderName());
- File binWorkDir = resolveBinaryWorkDir(cfg.getWorkDirectory(), settings.folderName());
+ File binWorkDir = binaryWorkDir(cfg.getWorkDirectory(), settings.folderName());
File marshWorkDir = mappingFileStoreWorkDir(U.workDirectory(cfg.getWorkDirectory(), cfg.getIgniteHome()));
- File snpBinWorkDir = resolveBinaryWorkDir(mgr.snapshotLocalDir(SNAPSHOT_NAME).getAbsolutePath(), settings.folderName());
+ File snpBinWorkDir = binaryWorkDir(mgr.snapshotLocalDir(SNAPSHOT_NAME).getAbsolutePath(), settings.folderName());
File snpMarshWorkDir = mappingFileStoreWorkDir(mgr.snapshotLocalDir(SNAPSHOT_NAME).getAbsolutePath());
final Map<String, Integer> origPartCRCs = calculateCRC32Partitions(cacheWorkDir);
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
index 7eae72d..25e44f9 100755
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
@@ -140,6 +140,7 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_EVENT_DRIVEN_SERVI
import static org.apache.ignite.IgniteSystemProperties.getBoolean;
import static org.apache.ignite.cache.CacheMode.LOCAL;
import static org.apache.ignite.cache.CacheRebalanceMode.NONE;
+import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_SNAPSHOT_DIRECTORY;
import static org.apache.ignite.internal.processors.cache.GridCacheUtils.isNearEnabled;
import static org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl.BINARY_META_FOLDER;
import static org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState.OWNING;
@@ -1929,6 +1930,7 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false));
U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), "marshaller", false));
U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), BINARY_META_FOLDER, false));
+ U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_SNAPSHOT_DIRECTORY, false));
}
/**
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 33215f1..998cb12 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -26,6 +26,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -112,7 +113,6 @@ import static org.apache.ignite.cache.PartitionLossPolicy.READ_ONLY_SAFE;
import static org.apache.ignite.cluster.ClusterState.ACTIVE;
import static org.apache.ignite.cluster.ClusterState.ACTIVE_READ_ONLY;
import static org.apache.ignite.cluster.ClusterState.INACTIVE;
-import static org.apache.ignite.configuration.IgniteConfiguration.DFLT_SNAPSHOT_DIRECTORY;
import static org.apache.ignite.events.EventType.EVT_NODE_FAILED;
import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
import static org.apache.ignite.internal.commandline.CommandHandler.CONFIRM_MSG;
@@ -121,6 +121,7 @@ import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_UNEXPECTED_ERROR;
import static org.apache.ignite.internal.commandline.CommandList.DEACTIVATE;
import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.MASTER_KEY_NAME_2;
+import static org.apache.ignite.internal.processors.cache.persistence.snapshot.AbstractSnapshotSelfTest.doSnapshotCancellationTest;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.SNAPSHOT_METRICS;
import static org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManager.resolveSnapshotWorkDirectory;
import static org.apache.ignite.internal.processors.cache.verify.IdleVerifyUtility.GRID_NOT_IDLE_MSG;
@@ -164,7 +165,6 @@ public class GridCommandHandlerTest extends GridCommandHandlerClusterPerMethodAb
super.cleanPersistenceDir();
cleanDiagnosticDir();
- U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_SNAPSHOT_DIRECTORY, false));
}
/**
@@ -2148,4 +2148,20 @@ public class GridCommandHandlerTest extends GridCommandHandlerClusterPerMethodAb
assertContains(log, testOut.toString(), "Snapshot operation has been rejected. The cluster is inactive.");
}
+
+ /** @throws Exception If fails. */
+ @Test
+ public void testCancelSnapshot() throws Exception {
+ IgniteEx srv = startGrid(0);
+ IgniteEx startCli = startClientGrid(CLIENT_NODE_NAME_PREFIX);
+
+ srv.cluster().state(ACTIVE);
+
+ createCacheAndPreload(startCli, 100);
+
+ CommandHandler h = new CommandHandler();
+
+ doSnapshotCancellationTest(startCli, Collections.singletonList(srv), startCli.cache(DEFAULT_CACHE_NAME),
+ snpName -> assertEquals(EXIT_CODE_OK, execute(h, "--snapshot", "cancel", snpName)));
+ }
}
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 2106289..6048c94 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
@@ -107,12 +107,24 @@ This utility can do the following commands:
routine_id - Routine identifier.
origin_node_id - Originating node id.
+ Kill running snapshot by snapshot name:
+ control.(sh|bat) --kill SNAPSHOT snapshot_name
+
+ Parameters:
+ snapshot_name - Snapshot name.
+
Create cluster snapshot:
control.(sh|bat) --snapshot create snapshot_name
Parameters:
snapshot_name - Snapshot name.
+ Cancel running snapshot:
+ control.(sh|bat) --snapshot cancel snapshot_name
+
+ Parameters:
+ snapshot_name - Snapshot name.
+
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 2106289..6048c94 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
@@ -107,12 +107,24 @@ This utility can do the following commands:
routine_id - Routine identifier.
origin_node_id - Originating node id.
+ Kill running snapshot by snapshot name:
+ control.(sh|bat) --kill SNAPSHOT snapshot_name
+
+ Parameters:
+ snapshot_name - Snapshot name.
+
Create cluster snapshot:
control.(sh|bat) --snapshot create snapshot_name
Parameters:
snapshot_name - Snapshot name.
+ Cancel running snapshot:
+ control.(sh|bat) --snapshot cancel snapshot_name
+
+ Parameters:
+ snapshot_name - Snapshot name.
+
By default commands affecting the cluster require interactive confirmation.
Use --yes option to disable it.
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotWithIndexesTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotWithIndexesTest.java
index 141b8bc..4f6663d 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotWithIndexesTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/persistence/snapshot/IgniteClusterSnapshotWithIndexesTest.java
@@ -17,12 +17,10 @@
package org.apache.ignite.internal.processors.cache.persistence.snapshot;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
@@ -137,18 +135,7 @@ public class IgniteClusterSnapshotWithIndexesTest extends AbstractSnapshotSelfTe
executeSql(ignite, "INSERT INTO " + tblName + " (id, name, age, city) VALUES(?, 'name', 3, 'city')", i);
// Blocking configuration local snapshot sender.
- List<BlockingExecutor> execs = new ArrayList<>();
-
- for (Ignite grid : G.allGrids()) {
- IgniteSnapshotManager mgr = snp((IgniteEx)grid);
- Function<String, SnapshotSender> old = mgr.localSnapshotSenderFactory();
-
- BlockingExecutor block = new BlockingExecutor(mgr.snapshotExecutorService());
- execs.add(block);
-
- mgr.localSnapshotSenderFactory((snpName) ->
- new DelegateSnapshotSender(log, block, old.apply(snpName)));
- }
+ List<BlockingExecutor> execs = setBlockingSnapshotExecutor(G.allGrids());
IgniteFuture<Void> fut = ignite.snapshot().createSnapshot(SNAPSHOT_NAME);
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
index f07f707..01d2ba6 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
@@ -60,6 +60,7 @@ import org.apache.ignite.configuration.SqlConfiguration;
import org.apache.ignite.configuration.TopologyValidator;
import org.apache.ignite.internal.ClusterMetricsSnapshot;
import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.IgniteNodeAttributes;
import org.apache.ignite.internal.managers.discovery.ClusterMetricsImpl;
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
@@ -83,6 +84,7 @@ import org.junit.Test;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toSet;
+import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
import static org.junit.Assert.assertNotEquals;
/**
@@ -391,21 +393,23 @@ public class SqlSystemViewsSelfTest extends AbstractIndexingCommonTest {
* @param cacheName Cache name.
* @param rebuild Is indexes rebuild in progress.
*/
- private void checkIndexRebuild(String cacheName, boolean rebuild) {
+ private void checkIndexRebuild(String cacheName, boolean rebuild) throws IgniteInterruptedCheckedException {
String idxSql = "SELECT IS_INDEX_REBUILD_IN_PROGRESS FROM " + systemSchemaName() + ".TABLES " +
"WHERE TABLE_NAME = ?";
- List<List<?>> res = execSql(grid(), idxSql, cacheName);
+ assertTrue(waitForCondition(() -> {
+ List<List<?>> res = execSql(grid(), idxSql, cacheName);
- assertFalse(res.isEmpty());
+ assertFalse(res.isEmpty());
- assertTrue(res.stream().allMatch(row -> {
- assertEquals(1, row.size());
+ return res.stream().allMatch(row -> {
+ assertEquals(1, row.size());
- Boolean isIndexRebuildInProgress = (Boolean)row.get(0);
+ Boolean isIndexRebuildInProgress = (Boolean)row.get(0);
- return isIndexRebuildInProgress == rebuild;
- }));
+ return isIndexRebuildInProgress == rebuild;
+ });
+ }, 5_000));
}
/**
diff --git a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java
index e8650ed..895f5ae 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java
@@ -28,12 +28,14 @@ import org.apache.ignite.lang.IgniteUuid;
import org.junit.Test;
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
+import static org.apache.ignite.internal.processors.cache.persistence.snapshot.AbstractSnapshotSelfTest.doSnapshotCancellationTest;
+import static org.apache.ignite.util.KillCommandsTests.PAGES_CNT;
import static org.apache.ignite.util.KillCommandsTests.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelContinuousQuery;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelSQLQuery;
-import static org.apache.ignite.util.KillCommandsTests.doTestCancelTx;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelService;
+import static org.apache.ignite.util.KillCommandsTests.doTestCancelTx;
import static org.apache.ignite.util.KillCommandsTests.doTestScanQueryCancel;
/** Tests cancel of user created entities via control.sh. */
@@ -54,7 +56,9 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
- for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ // There must be enough cache entries to keep scan query cursor opened.
+ // Cursor may be concurrently closed when all the data retrieved.
+ for (int i = 0; i < PAGES_CNT * PAGE_SZ; i++)
cache.put(i, i);
awaitPartitionMapExchange();
@@ -127,6 +131,24 @@ public class KillCommandsCommandShTest extends GridCommandHandlerClusterByClassA
/** */
@Test
+ public void testCancelSnapshot() {
+ doSnapshotCancellationTest(client, srvs, client.cache(DEFAULT_CACHE_NAME), snpName -> {
+ int res = execute("--kill", "snapshot", snpName);
+
+ assertEquals(EXIT_CODE_OK, res);
+ });
+ }
+
+ /** */
+ @Test
+ public void testCancelUnknownSnapshot() {
+ int res = execute("--kill", "snapshot", "unknown");
+
+ assertEquals(EXIT_CODE_OK, res);
+ }
+
+ /** */
+ @Test
public void testCancelUnknownScanQuery() {
int res = execute("--kill", "scan", srvs.get(0).localNode().id().toString(), "unknown", "1");
diff --git a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsMXBeanTest.java b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsMXBeanTest.java
index a8927b4..8bb08bd 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsMXBeanTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsMXBeanTest.java
@@ -23,20 +23,27 @@ import java.util.UUID;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.ComputeMXBeanImpl;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.QueryMXBeanImpl;
+import org.apache.ignite.internal.ServiceMXBeanImpl;
import org.apache.ignite.internal.TransactionsMXBeanImpl;
+import org.apache.ignite.internal.processors.cache.persistence.snapshot.SnapshotMXBeanImpl;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.mxbean.ComputeMXBean;
-import org.apache.ignite.internal.ServiceMXBeanImpl;
import org.apache.ignite.mxbean.QueryMXBean;
import org.apache.ignite.mxbean.ServiceMXBean;
+import org.apache.ignite.mxbean.SnapshotMXBean;
import org.apache.ignite.mxbean.TransactionsMXBean;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
import static org.apache.ignite.cluster.ClusterState.ACTIVE;
+import static org.apache.ignite.internal.processors.cache.persistence.snapshot.AbstractSnapshotSelfTest.doSnapshotCancellationTest;
+import static org.apache.ignite.util.KillCommandsTests.PAGES_CNT;
import static org.apache.ignite.util.KillCommandsTests.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelContinuousQuery;
@@ -71,8 +78,22 @@ public class KillCommandsMXBeanTest extends GridCommonAbstractTest {
/** */
private static ServiceMXBean svcMxBean;
+ /** Snapshot control JMX bean. */
+ private static SnapshotMXBean snpMxBean;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ return super.getConfiguration(igniteInstanceName)
+ .setDataStorageConfiguration(new DataStorageConfiguration()
+ .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+ .setMaxSize(100L * 1024 * 1024)
+ .setPersistenceEnabled(true)));
+ }
+
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
+ cleanPersistenceDir();
+
startGridsMultiThreaded(NODES_CNT);
srvs = new ArrayList<>();
@@ -89,7 +110,9 @@ public class KillCommandsMXBeanTest extends GridCommonAbstractTest {
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
- for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ // There must be enough cache entries to keep scan query cursor opened.
+ // Cursor may be concurrently closed when all the data retrieved.
+ for (int i = 0; i < PAGES_CNT * PAGE_SZ; i++)
cache.put(i, i);
qryMBean = getMxBean(killCli.name(), "Query",
@@ -103,6 +126,17 @@ public class KillCommandsMXBeanTest extends GridCommonAbstractTest {
svcMxBean = getMxBean(killCli.name(), "Service",
ServiceMXBeanImpl.class.getSimpleName(), ServiceMXBean.class);
+
+ snpMxBean = getMxBean(killCli.name(), "Snapshot",
+ SnapshotMXBeanImpl.class.getSimpleName(), SnapshotMXBean.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ super.afterTestsStopped();
+
+ stopAllGrids();
+ cleanPersistenceDir();
}
/** */
@@ -145,6 +179,19 @@ public class KillCommandsMXBeanTest extends GridCommonAbstractTest {
/** */
@Test
+ public void testCancelSnapshot() {
+ doSnapshotCancellationTest(startCli, srvs, startCli.cache(DEFAULT_CACHE_NAME),
+ snpName -> snpMxBean.cancelSnapshot(snpName));
+ }
+
+ /** */
+ @Test
+ public void testCancelUnknownSnapshot() {
+ snpMxBean.cancelSnapshot("unknown");
+ }
+
+ /** */
+ @Test
public void testCancelUnknownScanQuery() {
qryMBean.cancelScan(srvs.get(0).localNode().id().toString(), "unknown", 1L);
}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsSQLTest.java b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsSQLTest.java
index 5606175..cc03bc0 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsSQLTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsSQLTest.java
@@ -40,6 +40,7 @@ import static org.apache.ignite.internal.sql.SqlKeyword.SCAN;
import static org.apache.ignite.internal.sql.SqlKeyword.SERVICE;
import static org.apache.ignite.internal.sql.SqlKeyword.TRANSACTION;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
+import static org.apache.ignite.util.KillCommandsTests.PAGES_CNT;
import static org.apache.ignite.util.KillCommandsTests.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelContinuousQuery;
@@ -98,7 +99,9 @@ public class KillCommandsSQLTest extends GridCommonAbstractTest {
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
- for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ // There must be enough cache entries to keep scan query cursor opened.
+ // Cursor may be concurrently closed when all the data retrieved.
+ for (int i = 0; i < PAGES_CNT * PAGE_SZ; i++)
cache.put(i, i);
}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsTests.java b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsTests.java
index 520d85a..81b6abe 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsTests.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsTests.java
@@ -73,6 +73,9 @@ class KillCommandsTests {
/** Page size. */
public static final int PAGE_SZ = 5;
+ /** Number of pages to insert. */
+ public static final int PAGES_CNT = 1000;
+
/** Operations timeout. */
public static final int TIMEOUT = 10_000;
@@ -211,7 +214,8 @@ class KillCommandsTests {
public static void doTestCancelTx(IgniteEx cli, List<IgniteEx> srvs, Consumer<String> txCanceler) {
IgniteCache<Object, Object> cache = cli.cache(DEFAULT_CACHE_NAME);
- int testKey = 42;
+ // See e.g. KillCommandsMxBeanTest
+ int testKey = (PAGES_CNT * PAGE_SZ) + 42;
try (Transaction tx = cli.transactions().txStart()) {
cache.put(testKey, 1);