[NO ISSUE][OTH] Allow Cancellation of Requests Before Job Start

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Currently clients' requests are marked cancellable only after
  their jobs start. This change allows cancellation of a request
  after its job is compiled but before the job starts.

Change-Id: I8b7e811a16f37326d00d1b9d145819bdf6763fe0
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3182
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index df285c6..f89b2db 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -67,6 +67,7 @@
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.MetadataException;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.common.utils.JobUtils;
 import org.apache.asterix.common.utils.JobUtils.ProgressState;
@@ -2603,11 +2604,11 @@
             if (jobSpec == null) {
                 return;
             }
-            final JobId jobId = JobUtils.runJob(hcc, jobSpec, jobFlags, false);
-            clientRequest.setJobId(jobId);
             if (cancellable) {
                 clientRequest.markCancellable();
             }
+            final JobId jobId = JobUtils.runJob(hcc, jobSpec, jobFlags, false);
+            clientRequest.setJobId(jobId);
             if (jId != null) {
                 jId.setValue(jobId);
             }
@@ -2618,6 +2619,9 @@
                 hcc.waitForCompletion(jobId);
                 printer.print(jobId);
             }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeDataException(ErrorCode.REQUEST_CANCELLED, clientRequest.getId());
         } finally {
             // complete async jobs after their job completes
             if (ResultDelivery.ASYNC == resultDelivery) {
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
index 2a945e9..242c0dd 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/CancellationTestExecutor.java
@@ -114,8 +114,8 @@
             }
         }
         String errorMsg = ExceptionUtils.getErrorMessage(e);
-        // Expected, "HYR0025" means a user cancelled the query.)
-        if (errorMsg.startsWith("HYR0025")) {
+        // Expected, "HYR0025" or "ASX0041" means a user cancelled the query.)
+        if (errorMsg.startsWith("HYR0025") || errorMsg.startsWith("ASX0041")) {
             SqlppExecutionWithCancellationTest.numCancelledQueries++;
             queryCount.increment();
             return false;
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index d8a21f16..ecf4eff 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -80,6 +80,7 @@
     public static final int DIFFERENT_LIST_TYPE_ARGS = 38;
     public static final int INTEGER_VALUE_EXPECTED = 39;
     public static final int NO_STATEMENT_PROVIDED = 40;
+    public static final int REQUEST_CANCELLED = 41;
 
     public static final int UNSUPPORTED_JRE = 100;
 
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index b55f537..c1b5d47 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -74,6 +74,7 @@
 38 = Input contains different list types
 39 = Expected integer value, got %1$s
 40 = No statement provided
+41 = Request %1$s has been cancelled
 
 100 = Unsupported JRE: %1$s