This is an automated email from the ASF dual-hosted git repository.

alex-plekhanov 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 174bde616a1 IGNITE-28900 Control-utility: Add mass query cancellation 
command (#13420)
174bde616a1 is described below

commit 174bde616a1be5af556582ef2f67b34cf6d1be85
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Aug 20 17:10:06 2026 +0300

    IGNITE-28900 Control-utility: Add mass query cancellation command (#13420)
---
 docs/_docs/tools/control-script.adoc               |  59 ++++
 .../commandline/CommandHandlerParsingTest.java     |  19 ++
 .../testsuites/IgniteControlUtilityTestSuite.java  |   2 +
 .../ignite/util/KillAllCommandsControlShTest.java  | 333 +++++++++++++++++++++
 .../internal/management/kill/KillAllCommand.java   |  96 ++++++
 .../management/kill/KillAllCommandArg.java         | 129 ++++++++
 .../internal/management/kill/KillAllTask.java      | 287 ++++++++++++++++++
 .../management/kill/KillAllTaskResult.java         |  65 ++++
 .../internal/management/kill/KillCommand.java      |   1 +
 .../query/GridCacheDistributedQueryManager.java    |   5 +
 .../cache/query/GridCacheQueryFutureAdapter.java   |  20 +-
 .../continuous/CacheContinuousQueryHandler.java    |   7 +
 .../continuous/GridContinuousProcessor.java        |   4 +-
 .../ignite/internal/util/GridTestClockTimer.java   |   2 +
 ...ridCommandHandlerClusterByClassTest_help.output |  11 +
 ...andHandlerClusterByClassWithSSLTest_help.output |  11 +
 16 files changed, 1046 insertions(+), 5 deletions(-)

diff --git a/docs/_docs/tools/control-script.adoc 
b/docs/_docs/tools/control-script.adoc
index a4820d20a8c..fd96397f261 100644
--- a/docs/_docs/tools/control-script.adoc
+++ b/docs/_docs/tools/control-script.adoc
@@ -453,6 +453,65 @@ For example, to cancel the transactions that have been 
running for more than 100
 control.sh --tx --min-duration 100 --kill
 ----
 
+== Mass Cancellation of Queries
+
+The control script allows you to mass cancel SQL queries, scan queries, index 
queries and continuous queries that match specific criteria.
+
+The syntax for the mass cancellation command is as follows:
+
+[tabs]
+--
+tab:Unix[]
+[source,shell,subs="verbatim,quotes"]
+----
+control.sh --kill all <target> [--node-id <nodeId>] [--min-duration <seconds>]
+----
+tab:Windows[]
+[source,shell,subs="verbatim,quotes"]
+----
+control.bat --kill all <target> [--node-id <nodeId>] [--min-duration <seconds>]
+----
+--
+
+The following target types are supported:
+
+[cols="1,3",opts="header"]
+|===
+|Target | Description
+|`sql`| SQL queries
+|`scan`| Scan queries
+|`index`| Index queries
+|`continuous`| Continuous queries
+|===
+
+Parameters:
+
+[cols="2,5",opts="header"]
+|===
+|Parameter | Description
+|--nodeId <nodeId>| Optional. UUID of the originator node to filter targets.
+|--min-duration <seconds>| Optional. Minimum duration in seconds. Only objects 
that have been running longer than the specified value will be cancelled.
+|===
+
+Example commands:
+
+[source, shell]
+----
+# Cancel all SQL queries that have been running for more than 60 seconds
+control.sh --kill all sql --min-duration 60
+
+# Cancel scan queries that have been running for more than 30 seconds on a 
specific node
+control.sh --kill all scan --nodeId <uuid> --min-duration 30
+
+# Cancel index queries on a specific node
+control.sh --kill all index --nodeId <uuid>
+
+# Cancel continuous queries
+control.sh --kill all continuous
+----
+
+To cancel specific individual objects (without mass filtering) see 
link:sql-reference/operational-commands[Operational Commands] section.
+
 == Contention Detection in Transactions
 
 The `contention` command detects when multiple transactions are in contention 
to create a lock for the same key. The command is useful if you have 
long-running or hanging transactions.
diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
index c6b6c5b8a80..0fc350ab7c8 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
@@ -71,6 +71,8 @@ import 
org.apache.ignite.internal.management.encryption.EncryptionChangeMasterKe
 import org.apache.ignite.internal.management.encryption.EncryptionCommand;
 import org.apache.ignite.internal.management.event.EventCommand;
 import org.apache.ignite.internal.management.io.IoTestCommand;
+import org.apache.ignite.internal.management.kill.KillAllCommand;
+import org.apache.ignite.internal.management.kill.KillAllCommandArg;
 import org.apache.ignite.internal.management.kill.KillCommand;
 import org.apache.ignite.internal.management.meta.MetaCommand;
 import org.apache.ignite.internal.management.meta.MetaRemoveCommand;
@@ -479,6 +481,13 @@ public class CommandHandlerParsingTest {
 
                 arg = (A)a;
             }
+            else if (cmd.getClass() == KillAllCommand.class) {
+                KillAllCommandArg a = new KillAllCommandArg();
+
+                a.target(KillAllCommandArg.TargetType.SQL);
+
+                arg = (A)a;
+            }
             else
                 arg = cmd.argClass().newInstance();
 
@@ -524,6 +533,8 @@ public class CommandHandlerParsingTest {
             return;
         else if (cmd.getClass() == MetaRemoveCommand.class)
             cmdText = F.concat(cmdText, "--typeId", "1");
+        else if (cmd.getClass() == KillAllCommand.class)
+            cmdText = F.concat(cmdText, "SQL");
 
         args = parseArgs(asList(cmdText));
 
@@ -695,6 +706,14 @@ public class CommandHandlerParsingTest {
 
         assertParseArgsThrows("String representation of \"java.util.UUID\" is 
exepected", IllegalArgumentException.class,
             "--kill", "continuous", UUID.randomUUID().toString(), 
"not_a_uuid");
+
+        // Kill all command format errors.
+        assertParseArgsThrows("Argument target required.", "--kill", "all");
+        assertParseArgsThrows("Can't parse value 'unknown'", "--kill", "all", 
"unknown");
+        assertParseArgsThrows("Argument is invalid: --min-duration", "--kill", 
"all", "sql", "--min-duration", "-1");
+        assertParseArgsThrows("Argument is invalid: --min-duration", "--kill", 
"all", "sql", "--min-duration", "0");
+        assertParseArgsThrows("Argument is invalid: --minDuration is not 
supported for CONTINUOUS queries",
+            "--kill", "all", "continuous", "--min-duration", "60");
     }
 
     /**
diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
index 1c5701b6ada..6528d919f61 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java
@@ -42,6 +42,7 @@ import org.apache.ignite.util.GridCommandHandlerWalTest;
 import org.apache.ignite.util.GridCommandHandlerWithSslFactoryTest;
 import org.apache.ignite.util.GridCommandHandlerWithSslTest;
 import org.apache.ignite.util.GridPersistenceCommandsTest;
+import org.apache.ignite.util.KillAllCommandsControlShTest;
 import org.apache.ignite.util.KillCommandsControlShTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -76,6 +77,7 @@ import org.junit.runners.Suite;
     GridCommandHandlerLegacyClientTest.class,
 
     KillCommandsControlShTest.class,
+    KillAllCommandsControlShTest.class,
 
     BaselineEventsLocalTest.class,
     BaselineEventsRemoteTest.class,
diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/util/KillAllCommandsControlShTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/util/KillAllCommandsControlShTest.java
new file mode 100644
index 00000000000..607b97bcf0b
--- /dev/null
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/util/KillAllCommandsControlShTest.java
@@ -0,0 +1,333 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import java.util.function.ToIntFunction;
+import javax.cache.Cache;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.cache.query.IndexQuery;
+import org.apache.ignite.cache.query.Query;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import 
org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType;
+import org.apache.ignite.internal.util.GridTestClockTimer;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.systemview.view.SqlQueryView;
+import org.junit.Test;
+
+import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT;
+import static 
org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
+import static 
org.apache.ignite.internal.processors.query.running.RunningQueryManager.SQL_QRY_VIEW;
+import static org.apache.ignite.testframework.GridTestUtils.assertContains;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
+
+/**
+ * Test for mass queries cancellation.
+ */
+public class KillAllCommandsControlShTest extends 
GridCommandHandlerClusterByClassAbstractTest {
+    /** Operations timeout. */
+    public static final int TIMEOUT = 10_000;
+
+    /** */
+    private static final int ENTRIES_CNT = 1_000;
+
+    /** */
+    private static CountDownLatch latch;
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        IgniteCache<Object, Object> cache = client.getOrCreateCache(
+            new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+                .setIndexedTypes(Integer.class, Integer.class)
+                .setSqlFunctionClasses(SqlTestFunctions.class));
+
+        for (int i = 0; i < ENTRIES_CNT; i++)
+            cache.put(i, i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        latch = new CountDownLatch(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        latch.countDown();
+    }
+
+    /** */
+    @Test
+    public void testKillAllSql() {
+        String sql = "SELECT * FROM Integer WHERE latch()";
+
+        checkKillAll("sql", () -> new SqlFieldsQuery(sql), 
KillAllCommandsControlShTest::sqlQueriesCnt);
+    }
+
+    /** */
+    @Test
+    public void testKillAllScan() {
+        checkKillAll("scan", () -> new 
ScanQuery<>().setPageSize(1).setFilter((k, v) -> {
+            try {
+                latch.await(10, TimeUnit.SECONDS);
+            }
+            catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+
+            return true;
+        }), KillAllCommandsControlShTest::scanQueriesCnt);
+    }
+
+    /** */
+    @Test
+    public void testKillAllIndex() {
+        checkKillAll("index", () -> new 
IndexQuery<>(Integer.class).setFilter((k, v) -> {
+            try {
+                latch.await(10, TimeUnit.SECONDS);
+            }
+            catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+
+            return true;
+        }).setPageSize(1), KillAllCommandsControlShTest::indexQueriesCnt);
+    }
+
+    /** */
+    @Test
+    public void testKillAllContinuous() {
+        assertTrue(SERVER_NODE_CNT >= 2);
+
+        client.cache(DEFAULT_CACHE_NAME).query(new 
ContinuousQuery<>().setLocalListener(evts -> {}));
+        grid(0).cache(DEFAULT_CACHE_NAME).query(new 
ContinuousQuery<>().setLocalListener(evts -> {}));
+        grid(1).cache(DEFAULT_CACHE_NAME).query(new 
ContinuousQuery<>().setLocalListener(evts -> {}));
+
+        // Kill all queries using --node-id argument.
+        assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous",
+            "--node-id", grid(0).context().localNodeId().toString()));
+
+        assertEquals(1, 
client.context().continuous().localRoutineInfos().size());
+        assertEquals(0, 
grid(0).context().continuous().localRoutineInfos().size());
+        assertEquals(1, 
grid(1).context().continuous().localRoutineInfos().size());
+        assertEquals(0, 
client.context().continuous().remoteRoutineInfos().size());
+        assertEquals(2, 
grid(0).context().continuous().remoteRoutineInfos().size());
+        assertEquals(1, 
grid(1).context().continuous().remoteRoutineInfos().size());
+
+        // Kill all queries without arguments.
+        assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous"));
+
+        assertEquals(0, 
client.context().continuous().localRoutineInfos().size());
+        assertEquals(0, 
grid(0).context().continuous().localRoutineInfos().size());
+        assertEquals(0, 
grid(1).context().continuous().localRoutineInfos().size());
+        assertEquals(0, 
client.context().continuous().remoteRoutineInfos().size());
+        assertEquals(0, 
grid(0).context().continuous().remoteRoutineInfos().size());
+        assertEquals(0, 
grid(1).context().continuous().remoteRoutineInfos().size());
+    }
+
+    /** */
+    @Test
+    public void testKillUnrelated() {
+        try (
+            QueryCursor<Cache.Entry<Integer, Integer>> cur = 
client.cache(DEFAULT_CACHE_NAME)
+                .query(new IndexQuery<Integer, 
Integer>(Integer.class).setPageSize(1))
+        ) {
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "scan"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "sql"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous"));
+            assertEquals(ENTRIES_CNT, cur.getAll().size());
+        }
+
+        try (
+            QueryCursor<Cache.Entry<Integer, Integer>> cur = 
client.cache(DEFAULT_CACHE_NAME)
+                .query(new ScanQuery<Integer, Integer>().setPageSize(1))
+        ) {
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "index"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "sql"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous"));
+            assertEquals(ENTRIES_CNT, cur.getAll().size());
+        }
+
+        try (
+            FieldsQueryCursor<?> cur = client.cache(DEFAULT_CACHE_NAME)
+                .query(new SqlFieldsQuery("SELECT * FROM 
Integer").setPageSize(1))
+        ) {
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "scan"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "index"));
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous"));
+            assertEquals(ENTRIES_CNT, cur.getAll().size());
+        }
+    }
+
+    /** */
+    @Test
+    public void testRemoteListen() {
+        UUID evtLsnrId = client.events().remoteListen((nodeId, evt) -> true, 
evt -> true, EVT_CACHE_OBJECT_PUT);
+        UUID msgLsnrId = client.message().remoteListen("topic", (nodeId, msg) 
-> true);
+
+        try {
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", "continuous"));
+
+            boolean evtLsnrAlive = 
client.context().continuous().localRoutineInfos().containsKey(evtLsnrId);
+            boolean msgLsnrAlive = 
client.context().continuous().localRoutineInfos().containsKey(msgLsnrId);
+
+            assertTrue("Listeners were stopped", evtLsnrAlive && msgLsnrAlive);
+        }
+        finally {
+            client.events().stopRemoteListen(evtLsnrId);
+            client.message().stopRemoteListen(msgLsnrId);
+        }
+    }
+
+    /** */
+    public void checkKillAll(String target, Supplier<Query<?>> qryFactory, 
ToIntFunction<IgniteEx> qryCntProvider) {
+        try {
+            assertTrue(SERVER_NODE_CNT >= 2);
+
+            long ts = U.currentTimeMillis();
+            GridTestClockTimer.timeSupplier(() -> ts);
+
+            List<QueryCursor<?>> curs = new ArrayList<>();
+
+            curs.add(client.cache(DEFAULT_CACHE_NAME).query(qryFactory.get()));
+
+            for (int i = 0; i < 2; i++)
+                
curs.add(grid(i).cache(DEFAULT_CACHE_NAME).query(qryFactory.get()));
+
+            GridTestClockTimer.timeSupplier(() -> ts + 1001L);
+
+            curs.add(client.cache(DEFAULT_CACHE_NAME).query(qryFactory.get()));
+
+            for (int i = 0; i < 2; i++)
+                
curs.add(grid(i).cache(DEFAULT_CACHE_NAME).query(qryFactory.get()));
+
+            injectTestSystemOut();
+
+            // Kill all queries using both --min-duration and --node-id 
arguments.
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", target, 
"--min-duration", "1",
+                "--node-id", client.context().localNodeId().toString()));
+
+            assertContains(log, testOut.toString(), "Node ID: " + 
client.context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Total killed: 1");
+
+            assertEquals(1, qryCntProvider.applyAsInt(client));
+            assertEquals(2, qryCntProvider.applyAsInt(grid(0)));
+            assertEquals(2, qryCntProvider.applyAsInt(grid(1)));
+            assertThrows(log, () -> curs.get(0).getAll(), Exception.class, "");
+
+            testOut.reset();
+
+            // Kill all queries using --min-duration argument.
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", target, 
"--min-duration", "1"));
+            assertContains(log, testOut.toString(), "Node ID: " + 
grid(0).context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Node ID: " + 
grid(1).context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Total killed: 2");
+
+            assertEquals(1, qryCntProvider.applyAsInt(client));
+            assertEquals(1, qryCntProvider.applyAsInt(grid(0)));
+            assertEquals(1, qryCntProvider.applyAsInt(grid(1)));
+
+            assertThrows(log, () -> curs.get(1).getAll(), Exception.class, "");
+            assertThrows(log, () -> curs.get(2).getAll(), Exception.class, "");
+
+            testOut.reset();
+
+            // Kill all queries using --node-id argument.
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", target, 
"--node-id",
+                grid(0).context().localNodeId().toString()));
+
+            assertContains(log, testOut.toString(), "Node ID: " + 
grid(0).context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Total killed: 1");
+
+            assertEquals(1, qryCntProvider.applyAsInt(client));
+            assertEquals(0, qryCntProvider.applyAsInt(grid(0)));
+            assertEquals(1, qryCntProvider.applyAsInt(grid(1)));
+
+            assertThrows(log, () -> curs.get(4).getAll(), Exception.class, "");
+
+            testOut.reset();
+
+            // Kill all queries without arguments.
+            assertEquals(EXIT_CODE_OK, execute("--kill", "all", target));
+
+            assertContains(log, testOut.toString(), "Node ID: " + 
client.context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Node ID: " + 
grid(1).context().localNodeId() + " Killed: 1");
+            assertContains(log, testOut.toString(), "Total killed: 2");
+
+            assertEquals(0, qryCntProvider.applyAsInt(client));
+            assertEquals(0, qryCntProvider.applyAsInt(grid(0)));
+            assertEquals(0, qryCntProvider.applyAsInt(grid(1)));
+
+            assertThrows(log, () -> curs.get(3).getAll(), Exception.class, "");
+            assertThrows(log, () -> curs.get(5).getAll(), Exception.class, "");
+        }
+        finally {
+            
GridTestClockTimer.timeSupplier(GridTestClockTimer.DFLT_TIME_SUPPLIER);
+        }
+    }
+
+    /** */
+    private static int sqlQueriesCnt(IgniteEx ignite) {
+        return 
F.size(ignite.context().systemView().<SqlQueryView>view(SQL_QRY_VIEW).iterator(),
 v -> !v.mapQuery());
+    }
+
+    /** */
+    private static int scanQueriesCnt(IgniteEx ignite) {
+        return (int)((GridCacheDistributedQueryManager<?, 
?>)ignite.cachex(DEFAULT_CACHE_NAME).context().queries())
+            .distributedQueryFutures().stream().filter(f -> 
f.query().query().type() == GridCacheQueryType.SCAN).count();
+    }
+
+    /** */
+    private static int indexQueriesCnt(IgniteEx ignite) {
+        return (int)((GridCacheDistributedQueryManager<?, 
?>)ignite.cachex(DEFAULT_CACHE_NAME).context().queries())
+            .distributedQueryFutures().stream().filter(f -> 
f.query().query().type() == GridCacheQueryType.INDEX).count();
+    }
+
+    /** */
+    public static class SqlTestFunctions {
+        /** */
+        @QuerySqlFunction
+        public static boolean latch() {
+            try {
+                latch.await(TIMEOUT, TimeUnit.MILLISECONDS);
+            }
+            catch (InterruptedException ignored) {
+                return false;
+            }
+
+            return true;
+        }
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommand.java
new file mode 100644
index 00000000000..a3b590b28a0
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommand.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.kill;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.function.Consumer;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.management.api.CommandUtils;
+import org.apache.ignite.internal.management.api.ComputeCommand;
+
+/**
+ * Kill all command for mass cancellation of queries.
+ */
+public class KillAllCommand implements ComputeCommand<KillAllCommandArg, 
Map<ClusterNode, KillAllTaskResult>> {
+    /** {@inheritDoc} */
+    @Override public String description() {
+        return "Kill all SQL/scan/index/continuous queries matching specified 
criteria";
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<KillAllCommandArg> argClass() {
+        return KillAllCommandArg.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Class<KillAllTask> taskClass() {
+        return KillAllTask.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<ClusterNode> nodes(Collection<ClusterNode> 
nodes, KillAllCommandArg arg) {
+        return CommandUtils.nodeOrAll(arg.nodeId(), nodes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String confirmationPrompt(KillAllCommandArg arg) {
+        StringBuilder sb = new StringBuilder("Warning: the command will kill 
all ");
+
+        sb.append(arg.target().toString().toLowerCase()).append(" queries");
+
+        if (arg.minDuration() != null)
+            sb.append(" with duration > ").append(arg.minDuration()).append(" 
seconds");
+
+        if (arg.nodeId() != null)
+            sb.append(" on node ").append(arg.nodeId());
+
+        sb.append(".");
+
+        return sb.toString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void printResult(
+        KillAllCommandArg arg,
+        Map<ClusterNode, KillAllTaskResult> res,
+        Consumer<String> printer
+    ) {
+        if (res.isEmpty()) {
+            printer.accept("Nothing found.");
+            return;
+        }
+
+        int totalKilled = 0;
+        int totalFailed = 0;
+
+        for (Map.Entry<ClusterNode, KillAllTaskResult> entry : res.entrySet()) 
{
+            ClusterNode node = entry.getKey();
+            KillAllTaskResult result = entry.getValue();
+
+            totalKilled += result.killed();
+            totalFailed += result.failed();
+
+            if (result.killed() > 0 || result.failed() > 0)
+                printer.accept("Node ID: " + node.id() + " Killed: " + 
result.killed() + " Failed: " + result.failed());
+        }
+
+        printer.accept("\nTotal killed: " + totalKilled + ", failed to kill: " 
+ totalFailed + " "
+            + arg.target().toString().toLowerCase() + " queries");
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommandArg.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommandArg.java
new file mode 100644
index 00000000000..20a818b1713
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllCommandArg.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.kill;
+
+import java.util.UUID;
+import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.management.api.Argument;
+import org.apache.ignite.internal.management.api.CliConfirmArgument;
+import org.apache.ignite.internal.management.api.EnumDescription;
+import org.apache.ignite.internal.management.api.Positional;
+import org.apache.ignite.internal.util.typedef.internal.A;
+
+/**
+ * Argument for --kill all command.
+ */
+@CliConfirmArgument
+public class KillAllCommandArg extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Target type. */
+    @Order(0)
+    @Positional
+    @Argument()
+    @EnumDescription(
+        names = {
+            "SQL",
+            "SCAN",
+            "INDEX",
+            "CONTINUOUS"
+        },
+        descriptions = {
+            "SQL queries",
+            "SCAN queries",
+            "INDEX queries",
+            "CONTINUOUS queries"
+        }
+    )
+    TargetType target;
+
+    /** Node ID to filter targets. */
+    @Order(1)
+    @Argument(description = "Originating node ID to filter targets", optional 
= true)
+    UUID nodeId;
+
+    /** Minimum duration in seconds. */
+    @Order(2)
+    @Argument(description = "Minimum duration in seconds", example = "60", 
optional = true)
+    Long minDuration;
+
+    /**
+     * Target type enum.
+     */
+    public enum TargetType {
+        /** */
+        SQL,
+
+        /** */
+        SCAN,
+
+        /** */
+        INDEX,
+
+        /** */
+        CONTINUOUS
+    }
+
+    /**
+     * @return Target type.
+     */
+    public TargetType target() {
+        return target;
+    }
+
+    /**
+     * @param target Target type.
+     */
+    public void target(TargetType target) {
+        this.target = target;
+    }
+
+    /**
+     * @return Node ID.
+     */
+    public UUID nodeId() {
+        return nodeId;
+    }
+
+    /**
+     * @param nodeId Node ID.
+     */
+    public void nodeId(UUID nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    /**
+     * @return Minimum duration in seconds.
+     */
+    public Long minDuration() {
+        return minDuration;
+    }
+
+    /**
+     * @param minDuration Minimum duration in seconds.
+     */
+    public void minDuration(Long minDuration) {
+        A.ensure(minDuration == null || minDuration > 0, "--min-duration");
+        A.ensure(minDuration == null || target != TargetType.CONTINUOUS,
+            "--minDuration is not supported for CONTINUOUS queries");
+
+        this.minDuration = minDuration;
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTask.java
new file mode 100644
index 00000000000..ba610730f72
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTask.java
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.kill;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+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.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import 
org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryFuture;
+import 
org.apache.ignite.internal.processors.cache.query.GridCacheDistributedQueryManager;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType;
+import org.apache.ignite.internal.processors.cache.query.ScanQueryIterator;
+import 
org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryHandler;
+import 
org.apache.ignite.internal.processors.continuous.ContinousRoutineLocalInfo;
+import 
org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
+import 
org.apache.ignite.internal.processors.query.running.GridRunningQueryInfo;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorMultiNodeTask;
+import org.apache.ignite.resources.LoggerResource;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+/**
+ * Task to cancel multiple SQL queries, scan queries, continuous queries based 
on specified criteria.
+ */
+@GridInternal
+public class KillAllTask extends VisorMultiNodeTask<KillAllCommandArg, 
Map<ClusterNode, KillAllTaskResult>, KillAllTaskResult> {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** {@inheritDoc} */
+    @Override protected VisorJob<KillAllCommandArg, KillAllTaskResult> 
job(KillAllCommandArg arg) {
+        return new KillAllJob(arg, debug);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Map<ClusterNode, KillAllTaskResult> reduce0(
+        List<ComputeJobResult> results
+    ) throws IgniteException {
+        Map<ClusterNode, KillAllTaskResult> mapRes = new HashMap<>();
+
+        for (ComputeJobResult result : results) {
+            if (result.getException() != null)
+                throw result.getException();
+
+            KillAllTaskResult data = result.getData();
+
+            if (data != null && (data.killed() > 0 || data.failed() > 0))
+                mapRes.put(result.getNode(), data);
+        }
+
+        return mapRes;
+    }
+
+    /**
+     * Job to cancel multiple targets on a node.
+     */
+    private static class KillAllJob extends VisorJob<KillAllCommandArg, 
KillAllTaskResult> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Injected logger. */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /**
+         * @param arg   Job argument.
+         * @param debug Debug flag.
+         */
+        protected KillAllJob(KillAllCommandArg arg, boolean debug) {
+            super(arg, debug);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected KillAllTaskResult run(KillAllCommandArg arg) 
throws IgniteException {
+            switch (arg.target()) {
+                case SQL:
+                    return cancelSqlQueries(arg);
+
+                case SCAN:
+                    return cancelScanQueries(arg);
+
+                case INDEX:
+                    return cancelIndexQueries(arg);
+
+                case CONTINUOUS:
+                    return cancelContinuousQueries(arg);
+
+                default:
+                    throw new IgniteException("Unknown target type: " + 
arg.target());
+            }
+        }
+
+        /**
+         * Cancel SQL queries matching criteria.
+         *
+         * @param arg Command argument.
+         * @return Result.
+         */
+        private KillAllTaskResult cancelSqlQueries(KillAllCommandArg arg) {
+            List<GridRunningQueryInfo> qrys = 
ignite.context().query().runningQueryManager().runningSqlQueries();
+
+            qrys.removeIf(qry -> qry.mapQuery() || (arg.minDuration() != null
+                && U.currentTimeMillis() - qry.startTime() <= 
SECONDS.toMillis(arg.minDuration())));
+
+            for (GridRunningQueryInfo qry : qrys)
+                
ignite.context().query().runningQueryManager().cancelLocalQuery(qry.id());
+
+            return new KillAllTaskResult(qrys.size(), 0);
+        }
+
+        /**
+         * Cancel scan queries matching criteria.
+         *
+         * @param arg Command argument.
+         * @return Result.
+         */
+        private KillAllTaskResult cancelScanQueries(KillAllCommandArg arg) {
+            long ts = arg.minDuration() == null ? 0 : U.currentTimeMillis() - 
SECONDS.toMillis(arg.minDuration());
+            int killed = 0;
+            int failed = 0;
+
+            for (GridCacheContext<?, ?> cctx : 
ignite.context().cache().context().cacheContexts()) {
+                // Scan queries can be registered in multiple structures. 
There is no single registry for all scan
+                // queries. To properly cancel a scan query, all relevant 
structures must be analyzed:
+                // - cctx.queries().localQueryIterators() - iterators for 
local-only scans and local parts of
+                //   distributed scans (on initiator node). If initiator is 
not affinity node, there will be no
+                //   local iterator for distributed scan.
+                // - cctx.queries().distributedQueryFutures() - futures for 
distributed scans (on initiator node).
+                //   For local-only data (REPLICATED cache or local scans), 
there will be no distributed future.
+                // - cctx.queries().queryIterators() - remote iterators for 
distributed scans (on affinity nodes).
+                //   Keyed by originator node ID, each entry contains map of 
requests to iterators.
+                // Correct way to kill scan (see also 
GridCacheDistributedQueryManager.scanQueryDistributed ->
+                // new GridCloseableIteratorAdapter.onClose)
+                // - Close local iterator (removes iterator from 
localQueryIterators())
+                // - Cancel distributed future (removes future from 
distrivuted future list, completes future,
+                //   sends cancel to remote nodes, removes iterator from 
queryIterrators() on remote nodes)
+                GridCacheDistributedQueryManager<?, ?> mgr = 
(GridCacheDistributedQueryManager<?, ?>)cctx.queries();
+
+                // Kill local-only scans and local part of distributed scans.
+                for (ScanQueryIterator<?, ?, ?> locIter : 
mgr.localQueryIterators()) {
+                    if (arg.minDuration() != null && locIter.startTime() >= ts)
+                        continue;
+
+                    try {
+                        locIter.close();
+
+                        killed++;
+                    }
+                    catch (IgniteCheckedException e) {
+                        log.warning("Failed to close local iterator for scan 
query", e);
+
+                        failed++;
+                    }
+                }
+
+                // Kill remote part of distributed scans.
+                for (GridCacheDistributedQueryFuture<?, ?, ?> fut : 
mgr.distributedQueryFutures()) {
+                    if (fut.query().query().type() != GridCacheQueryType.SCAN)
+                        continue;
+
+                    if (arg.minDuration() != null && fut.startTime() >= ts)
+                        continue;
+
+                    try {
+                        fut.cancel();
+
+                        if (!cctx.affinityNode()) // For affinity nodes killed 
count is already incremented by locIter.
+                            killed++;
+                    }
+                    catch (IgniteCheckedException e) {
+                        log.warning("Failed to cancel distributed query future 
for scan query", e);
+
+                        failed++;
+                    }
+                }
+            }
+
+            return new KillAllTaskResult(killed, failed);
+        }
+
+        /**
+         * Cancel index queries matching criteria.
+         *
+         * @param arg Command argument.
+         * @return Result.
+         */
+        private KillAllTaskResult cancelIndexQueries(KillAllCommandArg arg) {
+            long ts = arg.minDuration() == null ? 0 : U.currentTimeMillis() - 
SECONDS.toMillis(arg.minDuration());
+            int killed = 0;
+            int failed = 0;
+
+            // Distributed Index queries are registered in 
distributedQueryFutures structure (both local and remote part).
+            // But local-only queries are not registered in any structure at 
all, so local queries are not killable.
+            for (GridCacheContext<?, ?> cctx : 
ignite.context().cache().context().cacheContexts()) {
+                GridCacheDistributedQueryManager<?, ?> mgr = 
(GridCacheDistributedQueryManager<?, ?>)cctx.queries();
+
+                for (GridCacheDistributedQueryFuture<?, ?, ?> fut : 
mgr.distributedQueryFutures()) {
+                    if (fut.query().query().type() != GridCacheQueryType.INDEX)
+                        continue;
+
+                    if (arg.minDuration() != null && fut.startTime() >= ts)
+                        continue;
+
+                    try {
+                        fut.cancel();
+
+                        killed++;
+                    }
+                    catch (IgniteCheckedException e) {
+                        log.warning("Failed to cancel distributed query future 
for index query", e);
+
+                        failed++;
+                    }
+                }
+            }
+
+            return new KillAllTaskResult(killed, failed);
+        }
+
+        /**
+         * Cancel continuous queries matching criteria.
+         *
+         * @param arg Command argument.
+         * @return Result.
+         */
+        private KillAllTaskResult cancelContinuousQueries(KillAllCommandArg 
arg) {
+            GridContinuousProcessor proc = ignite.context().continuous();
+
+            List<IgniteInternalFuture<?>> futs = new ArrayList<>();
+
+            for (Map.Entry<UUID, ContinousRoutineLocalInfo> e : 
proc.localRoutineInfos().entrySet()) {
+                if (!e.getValue().handler().isQuery())
+                    continue;
+
+                if (e.getValue().handler() instanceof 
CacheContinuousQueryHandler<?, ?> h && h.internal())
+                    continue;
+
+                if (arg.nodeId == null || 
arg.nodeId.equals(e.getValue().nodeId()))
+                    futs.add(proc.stopRoutine(e.getKey()));
+            }
+
+            int killed = 0;
+            int failed = 0;
+
+            for (IgniteInternalFuture<?> fut : futs) {
+                try {
+                    fut.get();
+
+                    killed++;
+                }
+                catch (IgniteCheckedException e) {
+                    log.warning("Failed to stop continuous query routine", e);
+
+                    failed++;
+                }
+            }
+
+            return new KillAllTaskResult(killed, failed);
+        }
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTaskResult.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTaskResult.java
new file mode 100644
index 00000000000..8b61bc509a8
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillAllTaskResult.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.kill;
+
+import org.apache.ignite.internal.Order;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/**
+ * Task result.
+ */
+public class KillAllTaskResult extends IgniteDataTransferObject {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Number of killed targets. */
+    @Order(0)
+    int killed;
+
+    /** Number of failures. */
+    @Order(1)
+    int failed;
+
+    /** */
+    public KillAllTaskResult() {
+        // No-op.
+    }
+
+    /**
+     * @param killed Number of killed targets.
+     * @param failed Number of failures.
+     */
+    public KillAllTaskResult(int killed, int failed) {
+        this.killed = killed;
+        this.failed = failed;
+    }
+
+    /**
+     * @return Number of killed targets.
+     */
+    public int killed() {
+        return killed;
+    }
+
+    /**
+     * @return Number of failures.
+     */
+    public int failed() {
+        return failed;
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillCommand.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillCommand.java
index 5dcbacaa934..0abc330d952 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillCommand.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/KillCommand.java
@@ -24,6 +24,7 @@ public class KillCommand extends CommandRegistryImpl {
     /** */
     public KillCommand() {
         super(
+            new KillAllCommand(),
             new KillComputeCommand(),
             new KillServiceCommand(),
             new KillTransactionCommand(),
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheDistributedQueryManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheDistributedQueryManager.java
index 583d3006bc4..9ebdcbbc251 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheDistributedQueryManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheDistributedQueryManager.java
@@ -532,6 +532,11 @@ public class GridCacheDistributedQueryManager<K, V> 
extends GridCacheQueryManage
         return fut;
     }
 
+    /** */
+    public Collection<GridCacheDistributedQueryFuture<?, ?, ?>> 
distributedQueryFutures() {
+        return futs.values();
+    }
+
     /** {@inheritDoc} */
     @SuppressWarnings({"unchecked"})
     @Override public GridCloseableIterator scanQueryDistributed(final 
CacheQuery qry,
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
index 2dcc4aa59da..7cbe82234e9 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryFutureAdapter.java
@@ -24,6 +24,7 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.query.QueryCancelledException;
 import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
 import org.apache.ignite.internal.cache.query.index.IndexQueryResultMeta;
 import org.apache.ignite.internal.processors.cache.CacheObjectUtils;
@@ -76,6 +77,9 @@ public abstract class GridCacheQueryFutureAdapter<K, V, R> 
extends GridFutureAda
     /** */
     private final IgniteUuid timeoutId = IgniteUuid.randomUuid();
 
+    /** */
+    private long startTime;
+
     /** */
     private long endTime;
 
@@ -103,7 +107,7 @@ public abstract class GridCacheQueryFutureAdapter<K, V, R> 
extends GridFutureAda
         if (log == null)
             log = U.logger(cctx.kernalContext(), logRef, 
GridCacheQueryFutureAdapter.class);
 
-        long startTime = U.currentTimeMillis();
+        startTime = U.currentTimeMillis();
 
         long timeout = qry.query().timeout();
         capacity = query().query().limit();
@@ -188,10 +192,15 @@ public abstract class GridCacheQueryFutureAdapter<K, V, 
R> extends GridFutureAda
      * @throws IgniteCheckedException If future is done with an error.
      */
     private void checkError() throws IgniteCheckedException {
-        if (error() != null) {
+        Throwable err = error();
+
+        if (err == null && isCancelled())
+            err = new QueryCancelledException("Query was cancelled");
+
+        if (err != null) {
             clear();
 
-            throw U.cast(error());
+            throw U.cast(err);
         }
     }
 
@@ -386,6 +395,11 @@ public abstract class GridCacheQueryFutureAdapter<K, V, R> 
extends GridFutureAda
         return timeoutId;
     }
 
+    /** Query start time. */
+    public long startTime() {
+        return startTime;
+    }
+
     /** {@inheritDoc} */
     @Override public long endTime() {
         return endTime;
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
index fca3a2b0037..4bb6c6fc754 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
@@ -408,6 +408,13 @@ public final class CacheContinuousQueryHandler<K, V> 
implements GridContinuousHa
         this.internal = internal;
     }
 
+    /**
+     * @return {@code True} if query is internal.
+     */
+    public boolean internal() {
+        return internal;
+    }
+
     /**
      * @param notifyExisting Notify existing.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
index 7570b94f37e..b1c9618ba28 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
@@ -324,12 +324,12 @@ public class GridContinuousProcessor extends 
GridProcessorAdapter {
     }
 
     /** */
-    Map<UUID, RemoteRoutineInfo> remoteRoutineInfos() {
+    public Map<UUID, RemoteRoutineInfo> remoteRoutineInfos() {
         return Collections.unmodifiableMap(rmtInfos);
     }
 
     /** */
-    Map<UUID, ContinousRoutineLocalInfo> localRoutineInfos() {
+    public Map<UUID, ContinousRoutineLocalInfo> localRoutineInfos() {
         return Collections.unmodifiableMap(locInfos);
     }
 
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/util/GridTestClockTimer.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/util/GridTestClockTimer.java
index eba1e484200..bdeb7e3065d 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/util/GridTestClockTimer.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/util/GridTestClockTimer.java
@@ -59,6 +59,8 @@ public class GridTestClockTimer implements Runnable {
      */
     public static void timeSupplier(LongSupplier timeSupplier) {
         GridTestClockTimer.timeSupplier = timeSupplier;
+
+        update();
     }
 
     /**
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 51554d2a892..dd6ff4e43ca 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
@@ -162,6 +162,17 @@ This utility can do the following commands:
     Parameters:
       new_limit  - Decimal value to change re-encryption rate limit (MB/s).
 
+  Kill all SQL/scan/index/continuous queries matching specified criteria:
+    control.(sh|bat) --kill all SQL|SCAN|INDEX|CONTINUOUS [--node-id node_id] 
[--min-duration 60] [--yes]
+
+    Parameters:
+      SQL                - SQL queries.
+      SCAN               - SCAN queries.
+      INDEX              - INDEX queries.
+      CONTINUOUS         - CONTINUOUS queries.
+      --node-id node_id  - Originating node ID to filter targets.
+      --min-duration 60  - Minimum duration in seconds.
+
   Kill compute task by session id:
     control.(sh|bat) --kill compute session_id
 
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 6254a020a6f..76f0f8c7e0e 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
@@ -162,6 +162,17 @@ This utility can do the following commands:
     Parameters:
       new_limit  - Decimal value to change re-encryption rate limit (MB/s).
 
+  Kill all SQL/scan/index/continuous queries matching specified criteria:
+    control.(sh|bat) --kill all SQL|SCAN|INDEX|CONTINUOUS [--node-id node_id] 
[--min-duration 60] [--yes]
+
+    Parameters:
+      SQL                - SQL queries.
+      SCAN               - SCAN queries.
+      INDEX              - INDEX queries.
+      CONTINUOUS         - CONTINUOUS queries.
+      --node-id node_id  - Originating node ID to filter targets.
+      --min-duration 60  - Minimum duration in seconds.
+
   Kill compute task by session id:
     control.(sh|bat) --kill compute session_id
 

Reply via email to