IGNITE-12815: SQL query cancel command. (#7580)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/QueryMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/QueryMXBeanImpl.java
new file mode 100644
index 0000000..e8d8cba
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/QueryMXBeanImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import java.util.UUID;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.cluster.IgniteClusterImpl;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+import org.apache.ignite.internal.visor.query.VisorQueryCancelOnInitiatorTask;
+import org.apache.ignite.internal.visor.query.VisorQueryCancelOnInitiatorTaskArg;
+import org.apache.ignite.mxbean.QueryMXBean;
+
+import static org.apache.ignite.internal.sql.command.SqlKillQueryCommand.parseGlobalQueryId;
+
+/**
+ * QueryMXBean implementation.
+ */
+public class QueryMXBeanImpl implements QueryMXBean {
+ /** Global query id format. */
+ public static final String EXPECTED_GLOBAL_QRY_ID_FORMAT = "Global query id should have format " +
+ "'{node_id}_{query_id}', e.g. '6fa749ee-7cf8-4635-be10-36a1c75267a7_54321'";
+
+ /** Kernal context. */
+ private final GridKernalContext ctx;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /**
+ * @param ctx Context.
+ */
+ public QueryMXBeanImpl(GridKernalContext ctx) {
+ this.ctx = ctx;
+ this.log = ctx.log(QueryMXBeanImpl.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void cancelSQL(String id) {
+ A.notNull(id, "id");
+
+ if (log.isInfoEnabled())
+ log.info("Killing sql query[id=" + id + ']');
+
+ try {
+ IgniteClusterImpl cluster = ctx.cluster().get();
+
+ T2<UUID, Long> ids = parseGlobalQueryId(id);
+
+ if (ids == null)
+ throw new IllegalArgumentException("Expected global query id. " + EXPECTED_GLOBAL_QRY_ID_FORMAT);
+
+ cluster.compute().execute(new VisorQueryCancelOnInitiatorTask(),
+ new VisorTaskArgument<>(ids.get1(), new VisorQueryCancelOnInitiatorTaskArg(ids.get1(), ids.get2()),
+ false));
+ }
+ catch (IgniteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
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 d600fd3..4613ab6 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
@@ -17,14 +17,19 @@
package org.apache.ignite.internal.commandline.query;
+import java.util.UUID;
import java.util.logging.Logger;
import org.apache.ignite.internal.client.GridClient;
import org.apache.ignite.internal.client.GridClientConfiguration;
import org.apache.ignite.internal.commandline.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.query.VisorQueryCancelOnInitiatorTask;
+import org.apache.ignite.internal.visor.query.VisorQueryCancelOnInitiatorTaskArg;
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;
@@ -36,16 +41,20 @@
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.SERVICE;
import static org.apache.ignite.internal.commandline.query.KillSubcommand.COMPUTE;
+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;
/**
* control.sh kill command.
*
* @see KillSubcommand
+ * @see QueryMXBean
* @see ServiceMXBean
* @see ComputeMXBean
* @see TransactionsMXBean
@@ -118,6 +127,18 @@
break;
+ case SQL:
+ T2<UUID, Long> ids = parseGlobalQueryId(argIter.nextArg("Expected SQL query id."));
+
+ if (ids == null)
+ throw new IllegalArgumentException("Expected global query id. " + EXPECTED_GLOBAL_QRY_ID_FORMAT);
+
+ taskArgs = new VisorQueryCancelOnInitiatorTaskArg(ids.get1(), ids.get2());
+
+ taskName = VisorQueryCancelOnInitiatorTask.class.getName();
+
+ break;
+
default:
throw new IllegalArgumentException("Unknown kill subcommand: " + cmd);
}
@@ -133,6 +154,9 @@
Command.usage(log, "Kill transaction by xid:", KILL, singletonMap("xid", "Transaction identifier."),
TRANSACTION.toString(), "xid");
+
+ Command.usage(log, "Kill sql query by query id:", KILL, singletonMap("query_id", "Query identifier."),
+ SQL.toString(), "query_id");
}
/** {@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 d07a27d..1e05435 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
@@ -18,6 +18,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.TransactionsMXBean;
@@ -25,6 +26,7 @@
* Subcommands of the kill command.
*
* @see KillCommand
+ * @see QueryMXBean
* @see ComputeMXBean
* @see TransactionsMXBean
* @see ServiceMXBean
@@ -37,5 +39,8 @@
TRANSACTION,
/** Kill service. */
- SERVICE
+ SERVICE,
+
+ /** Kill sql query. */
+ SQL
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/IgniteMBeansManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/IgniteMBeansManager.java
index 3fae961..d31f3ba 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/IgniteMBeansManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/IgniteMBeansManager.java
@@ -31,6 +31,7 @@
import org.apache.ignite.internal.GridKernalContextImpl;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.ServiceMXBeanImpl;
+import org.apache.ignite.internal.QueryMXBeanImpl;
import org.apache.ignite.internal.StripedExecutorMXBeanAdapter;
import org.apache.ignite.internal.ThreadPoolMXBeanAdapter;
import org.apache.ignite.internal.TransactionMetricsMxBeanImpl;
@@ -53,6 +54,7 @@
import org.apache.ignite.mxbean.IgniteMXBean;
import org.apache.ignite.mxbean.MetricsMxBean;
import org.apache.ignite.mxbean.ServiceMXBean;
+import org.apache.ignite.mxbean.QueryMXBean;
import org.apache.ignite.mxbean.StripedExecutorMXBean;
import org.apache.ignite.mxbean.ThreadPoolMXBean;
import org.apache.ignite.mxbean.TransactionMetricsMxBean;
@@ -151,6 +153,10 @@
TransactionsMXBean txMXBean = new TransactionsMXBeanImpl(ctx);
registerMBean("Transactions", txMXBean.getClass().getSimpleName(), txMXBean, TransactionsMXBean.class);
+ // Queries management
+ QueryMXBean qryMXBean = new QueryMXBeanImpl(ctx);
+ registerMBean("Query", qryMXBean.getClass().getSimpleName(), qryMXBean, QueryMXBean.class);
+
// Compute task management
ComputeMXBean computeMXBean = new ComputeMXBeanImpl(ctx);
registerMBean("Compute", computeMXBean.getClass().getSimpleName(), computeMXBean, ComputeMXBean.class);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlKillQueryCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlKillQueryCommand.java
index 604c27f..81638cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlKillQueryCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlKillQueryCommand.java
@@ -22,18 +22,22 @@
import org.apache.ignite.internal.sql.SqlLexer;
import org.apache.ignite.internal.sql.SqlLexerTokenType;
import org.apache.ignite.internal.sql.SqlParserUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.mxbean.QueryMXBean;
+import org.apache.ignite.spi.systemview.view.SqlQueryView;
+
+import static org.apache.ignite.internal.QueryMXBeanImpl.EXPECTED_GLOBAL_QRY_ID_FORMAT;
/**
* KILL QUERY command.
+ *
+ * @see QueryMXBean#cancelSQL(String)
+ * @see SqlQueryView#queryId()
*/
public class SqlKillQueryCommand implements SqlCommand {
/** */
private static final String ASYNC = "ASYNC";
- /** */
- private static final String EXPECTED_GLOBAL_QRY_ID_FORMAT = "Global query id should have format " +
- "'{node_id}_{query_id}', e.g. '6fa749ee-7cf8-4635-be10-36a1c75267a7_54321'";
-
/** Node query id. */
private long nodeQryId;
@@ -62,22 +66,16 @@
if (lex.tokenType() == SqlLexerTokenType.STRING) {
String tok = lex.token();
- String[] ids = tok.split("_");
+ T2<UUID, Long> ids = parseGlobalQueryId(tok);
- if (ids.length == 2) {
- try {
- nodeId = UUID.fromString(ids[0]);
+ if (ids == null)
+ throw SqlParserUtils.error(lex, EXPECTED_GLOBAL_QRY_ID_FORMAT);
- nodeQryId = Long.parseLong(ids[1]);
+ nodeId = ids.get1();
- return;
- }
- catch (Exception ignore) {
- // Fall through.
- }
+ nodeQryId = ids.get2();
- throw SqlParserUtils.error(lex, EXPECTED_GLOBAL_QRY_ID_FORMAT);
- }
+ return;
}
}
@@ -99,6 +97,27 @@
}
/**
+ * Parse global SQL query id.
+ * Format is {origin_node_id}_{query_id}.
+ *
+ * @param globalQryId Global query id.
+ * @return Results of parsing of {@code null} if parse failed.
+ */
+ public static T2<UUID, Long> parseGlobalQueryId(String globalQryId) {
+ String[] ids = globalQryId.split("_");
+
+ if (ids.length != 2)
+ return null;
+
+ try {
+ return new T2<>(UUID.fromString(ids[0]), Long.parseLong(ids[1]));
+ }
+ catch (Exception ignore) {
+ return null;
+ }
+ }
+
+ /**
* @return Node query id.
*/
public long nodeQueryId() {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTask.java
new file mode 100644
index 0000000..c1ae710
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTask.java
@@ -0,0 +1,85 @@
+/*
+ * 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.query;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.task.GridInternal;
+import org.apache.ignite.internal.processors.task.GridVisorManagementTask;
+import org.apache.ignite.internal.visor.VisorJob;
+import org.apache.ignite.internal.visor.VisorOneNodeTask;
+import org.apache.ignite.lang.IgniteClosure;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Task to cancel queries on initiator node.
+ */
+@GridInternal
+@GridVisorManagementTask
+public class VisorQueryCancelOnInitiatorTask extends VisorOneNodeTask<VisorQueryCancelOnInitiatorTaskArg, Void> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** {@inheritDoc} */
+ @Override protected VisorCancelQueryOnInitiatorJob job(VisorQueryCancelOnInitiatorTaskArg arg) {
+ return new VisorCancelQueryOnInitiatorJob(arg, debug);
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override protected Void reduce0(List<ComputeJobResult> results) throws IgniteException {
+ return null;
+ }
+
+ /** Job to cancel query on node. */
+ private static class VisorCancelQueryOnInitiatorJob extends VisorJob<VisorQueryCancelOnInitiatorTaskArg, Void> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * Create job with specified argument.
+ *
+ * @param arg Job argument.
+ * @param debug Flag indicating whether debug information should be printed into node log.
+ */
+ protected VisorCancelQueryOnInitiatorJob(VisorQueryCancelOnInitiatorTaskArg arg, boolean debug) {
+ super(arg, debug);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Void run(VisorQueryCancelOnInitiatorTaskArg arg) throws IgniteException {
+ ignite.compute(ignite.cluster().forNodeId(arg.getNodeId())).broadcast(new IgniteClosure<Long, Void>() {
+ /** Auto-injected grid instance. */
+ @IgniteInstanceResource
+ private transient IgniteEx ignite;
+
+ /** {@inheritDoc} */
+ @Override public Void apply(Long qryId) {
+ ignite.context().query().cancelQueries(Collections.singleton(arg.getQueryId()));
+
+ return null;
+ }
+ }, arg.getQueryId());
+
+ return null;
+ }
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTaskArg.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTaskArg.java
new file mode 100644
index 0000000..ba8e30a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryCancelOnInitiatorTaskArg.java
@@ -0,0 +1,81 @@
+/*
+ * 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.query;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.UUID;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * Arguments for task {@link VisorQueryCancelOnInitiatorTask}.
+ */
+public class VisorQueryCancelOnInitiatorTaskArg extends IgniteDataTransferObject {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Query initiator. */
+ private UUID nodeId;
+
+ /** Query ID to cancel. */
+ private long qryId;
+
+ /** Default constructor. */
+ public VisorQueryCancelOnInitiatorTaskArg() {
+ // No-op.
+ }
+
+ /**
+ * @param qryId Query id.
+ * @param nodeId Query initiator.
+ */
+ public VisorQueryCancelOnInitiatorTaskArg(UUID nodeId, long qryId) {
+ this.nodeId = nodeId;
+ this.qryId = qryId;
+ }
+
+ /** @return Query initiator. */
+ public UUID getNodeId() {
+ return nodeId;
+ }
+
+ /** @return Query ID to cancel. */
+ public long getQueryId() {
+ return qryId;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void writeExternalData(ObjectOutput out) throws IOException {
+ U.writeUuid(out, nodeId);
+ out.writeLong(qryId);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void readExternalData(byte protoVer, ObjectInput in) throws IOException, ClassNotFoundException {
+ nodeId = U.readUuid(in);
+ qryId = in.readLong();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(VisorQueryCancelOnInitiatorTaskArg.class, this);
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/mxbean/QueryMXBean.java b/modules/core/src/main/java/org/apache/ignite/mxbean/QueryMXBean.java
new file mode 100644
index 0000000..5721c78
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/mxbean/QueryMXBean.java
@@ -0,0 +1,36 @@
+/*
+ * 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.mxbean;
+
+import org.apache.ignite.spi.systemview.view.SqlQueryView;
+
+/**
+ * Query MXBean interface.
+ */
+public interface QueryMXBean {
+ /**
+ * Kills SQL query by the identifier.
+ *
+ * @param id SQL query id.
+ * @see SqlQueryView#queryId()
+ */
+ @MXBeanDescription("Kills SQL query by the identifier.")
+ void cancelSQL(
+ @MXBeanParameter(name = "id", description = "SQL query id.") String id
+ );
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
index d884ac5..dd4faa8 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/commandline/CommandHandlerParsingTest.java
@@ -47,6 +47,7 @@
import static java.util.Arrays.asList;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_ENABLE_EXPERIMENTAL_COMMAND;
+import static org.apache.ignite.internal.QueryMXBeanImpl.EXPECTED_GLOBAL_QRY_ID_FORMAT;
import static org.apache.ignite.internal.commandline.CommandList.CACHE;
import static org.apache.ignite.internal.commandline.CommandList.SET_STATE;
import static org.apache.ignite.internal.commandline.CommandList.WAL;
@@ -532,6 +533,15 @@
// Service command format errors.
assertParseArgsThrows("Expected service name.", "--kill", "service");
+
+ // Transaction command format errors.
+ assertParseArgsThrows("Expected transaction id.", "--kill", "transaction");
+
+ // SQL command format errors.
+ assertParseArgsThrows("Expected SQL query id.", "--kill", "sql");
+
+ assertParseArgsThrows("Expected global query id. " + EXPECTED_GLOBAL_QRY_ID_FORMAT,
+ "--kill", "sql", "not_sql_id");
}
/**
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 0f91993..5c90dac 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
@@ -86,6 +86,12 @@
Parameters:
xid - Transaction identifier.
+ Kill sql query by query id:
+ control.(sh|bat) --kill SQL query_id
+
+ Parameters:
+ query_id - Query identifier.
+
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 0f91993..5c90dac 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
@@ -86,6 +86,12 @@
Parameters:
xid - Transaction identifier.
+ Kill sql query by query id:
+ control.(sh|bat) --kill SQL query_id
+
+ Parameters:
+ query_id - Query identifier.
+
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/util/KillCommandsCommandShTest.java b/modules/indexing/src/test/java/org/apache/ignite/util/KillCommandsCommandShTest.java
index a0f52f7..9d045e7 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
@@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.IgniteEx;
@@ -26,7 +27,9 @@
import org.junit.Test;
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
+import static org.apache.ignite.util.KillCommandsTests.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
+import static org.apache.ignite.util.KillCommandsTests.doTestCancelSQLQuery;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelTx;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelService;
@@ -44,10 +47,13 @@
for (int i = 0; i < SERVER_NODE_CNT; i++)
srvs.add(grid(i));
- client.getOrCreateCache(
+ IgniteCache<Object, Object> cache = client.getOrCreateCache(
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
+ for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ cache.put(i, i);
+
awaitPartitionMapExchange();
}
@@ -88,6 +94,16 @@
/** */
@Test
+ public void testCancelSQLQuery() {
+ doTestCancelSQLQuery(client, qryId -> {
+ int res = execute("--kill", "sql", qryId);
+
+ assertEquals(EXIT_CODE_OK, res);
+ });
+ }
+
+ /** */
+ @Test
public void testCancelUnknownComputeTask() {
int res = execute("--kill", "compute", IgniteUuid.randomUuid().toString());
@@ -109,4 +125,12 @@
assertEquals(EXIT_CODE_OK, res);
}
+
+ /** */
+ @Test
+ public void testCancelUnknownSQLQuery() {
+ int res = execute("--kill", "sql", srvs.get(0).localNode().id().toString() + "_42");
+
+ assertEquals(EXIT_CODE_OK, res);
+ }
}
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 000e3c2..4c22326 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
@@ -19,21 +19,26 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.ComputeMXBeanImpl;
import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.QueryMXBeanImpl;
import org.apache.ignite.internal.TransactionsMXBeanImpl;
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.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.util.KillCommandsTests.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
+import static org.apache.ignite.util.KillCommandsTests.doTestCancelSQLQuery;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelService;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelTx;
@@ -52,6 +57,9 @@
private static IgniteEx killCli;
/** */
+ private static QueryMXBean qryMBean;
+
+ /** */
private static TransactionsMXBean txMBean;
/** */
@@ -74,10 +82,16 @@
srvs.get(0).cluster().state(ACTIVE);
- startCli.getOrCreateCache(
+ IgniteCache<Object, Object> cache = startCli.getOrCreateCache(
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
+ for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ cache.put(i, i);
+
+ qryMBean = getMxBean(killCli.name(), "Query",
+ QueryMXBeanImpl.class.getSimpleName(), QueryMXBean.class);
+
txMBean = getMxBean(killCli.name(), "Transactions",
TransactionsMXBeanImpl.class.getSimpleName(), TransactionsMXBean.class);
@@ -108,6 +122,12 @@
/** */
@Test
+ public void testCancelSQLQuery() {
+ doTestCancelSQLQuery(startCli, qryId -> qryMBean.cancelSQL(qryId));
+ }
+
+ /** */
+ @Test
public void testCancelUnknownComputeTask() {
computeMBean.cancel(IgniteUuid.randomUuid().toString());
}
@@ -123,4 +143,10 @@
public void testCancelUnknownService() {
svcMxBean.cancel("unknown");
}
+
+ /** */
+ @Test
+ public void testCancelUnknownSQLQuery() {
+ qryMBean.cancelSQL(srvs.get(0).localNode().id().toString() + "_42");
+ }
}
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 f23f522..5dc5c21 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
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.List;
import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.configuration.CacheConfiguration;
@@ -32,9 +33,13 @@
import static org.apache.ignite.internal.processors.cache.index.AbstractSchemaSelfTest.queryProcessor;
import static org.apache.ignite.internal.sql.SqlKeyword.COMPUTE;
import static org.apache.ignite.internal.sql.SqlKeyword.KILL;
+import static org.apache.ignite.internal.sql.SqlKeyword.QUERY;
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.PAGE_SZ;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelComputeTask;
+import static org.apache.ignite.util.KillCommandsTests.doTestCancelSQLQuery;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelService;
import static org.apache.ignite.util.KillCommandsTests.doTestCancelTx;
@@ -44,6 +49,9 @@
public static final int NODES_CNT = 3;
/** */
+ public static final String KILL_SQL_QRY = KILL + " " + QUERY;
+
+ /** */
public static final String KILL_COMPUTE_QRY = KILL + " " + COMPUTE;
/** */
@@ -75,9 +83,12 @@
srvs.get(0).cluster().state(ACTIVE);
- startCli.getOrCreateCache(
+ IgniteCache<Object, Object> cache = startCli.getOrCreateCache(
new CacheConfiguration<>(DEFAULT_CACHE_NAME).setIndexedTypes(Integer.class, Integer.class)
.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL));
+
+ for (int i = 0; i < PAGE_SZ * PAGE_SZ; i++)
+ cache.put(i, i);
}
/** @throws Exception If failed. */
@@ -101,6 +112,12 @@
/** */
@Test
+ public void testCancelSQLQuery() {
+ doTestCancelSQLQuery(startCli, qryId -> execute(killCli, KILL_SQL_QRY + " '" + qryId + "'"));
+ }
+
+ /** */
+ @Test
public void testCancelUnknownComputeTask() {
execute(killCli, KILL_COMPUTE_QRY + " '" + IgniteUuid.randomUuid() + "'");
}
@@ -117,6 +134,14 @@
execute(killCli, KILL_TX_QRY + " 'unknown'");
}
+ /** */
+ @Test
+ public void testCancelUnknownSQLQuery() {
+ assertThrowsWithCause(
+ () -> execute(killCli, KILL_SQL_QRY + " '" + srvs.get(0).localNode().id().toString() + "_42'"),
+ RuntimeException.class);
+ }
+
/**
* Execute query on given node.
*
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 c580b05..fb944c2 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
@@ -18,11 +18,14 @@
package org.apache.ignite.util;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
+import javax.cache.CacheException;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.lang.IgniteFuture;
import org.apache.ignite.services.Service;
@@ -32,6 +35,7 @@
import org.apache.ignite.spi.systemview.view.SystemView;
import org.apache.ignite.transactions.Transaction;
+import static org.apache.ignite.internal.processors.cache.index.AbstractSchemaSelfTest.queryProcessor;
import static org.apache.ignite.internal.processors.service.IgniteServiceProcessor.SVCS_VIEW;
import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
@@ -51,6 +55,9 @@
/** Cache name. */
public static final String DEFAULT_CACHE_NAME = "default";
+ /** Page size. */
+ public static final int PAGE_SZ = 5;
+
/** Operations timeout. */
public static final int TIMEOUT = 10_000;
@@ -182,6 +189,36 @@
assertTrue(res);
}
+ /**
+ * Test cancel of the SQL query.
+ *
+ * @param cli Client node.
+ * @param qryCanceler Query cancel closure.
+ */
+ public static void doTestCancelSQLQuery(IgniteEx cli, Consumer<String> qryCanceler) {
+ String qryStr = "SELECT * FROM \"default\".Integer";
+
+ SqlFieldsQuery qry = new SqlFieldsQuery(qryStr).setPageSize(PAGE_SZ);
+ Iterator<List<?>> iter = queryProcessor(cli).querySqlFields(qry, true).iterator();
+
+ assertNotNull(iter.next());
+
+ List<List<?>> sqlQries = execute(cli, "SELECT * FROM SYS.SQL_QUERIES ORDER BY START_TIME");
+
+ assertEquals(2, sqlQries.size());
+
+ String qryId = (String)sqlQries.get(0).get(0);
+
+ assertEquals(qryStr, sqlQries.get(0).get(1));
+
+ qryCanceler.accept(qryId);
+
+ for (int i=0; i < PAGE_SZ - 2; i++)
+ assertNotNull(iter.next());
+
+ assertThrowsWithCause(iter::next, CacheException.class);
+ }
+
/** */
public interface TestService extends Service {
/** */