You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2021/08/21 12:03:31 UTC

[jena] branch main updated: JENA-2141: Additional timeout flag used for setup time

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

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 6d57b06  JENA-2141: Additional timeout flag used for setup time
     new d1111d7  Merge pull request #1051 from afs/jena2141-timeout
6d57b06 is described below

commit 6d57b066257c7e7d63d2447ec1dba2b0b5726936
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Fri Aug 20 12:01:44 2021 +0100

    JENA-2141: Additional timeout flag used for setup time
---
 .../java/org/apache/jena/sparql/ARQConstants.java  | 19 ++++++++----
 .../jena/sparql/engine/QueryExecutionBase.java     | 34 ++++++++++++++++++----
 .../engine/iterator/QueryIterProcessBinding.java   | 25 ++++++++++++++--
 3 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java b/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
index 336dbc8..0a2ff4d 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
@@ -189,10 +189,10 @@ public class ARQConstants
     //public static final String allocGlobalVarMarker     = allocVarMarker+globalVar ;    // VarAlloc
     public static final String allocPathVariables       = allocVarAnonMarker+"P" ;      // PathCompiler
     public static final String allocQueryVariables      = allocVarMarker ;              // Query
-    
+
     /** Marker for RDF-star variables */
     public static final String allocVarTripleTerm      = "~";                           // RX, SolverRX
-    
+
     public static final String allocParserAnonVars      = allocVarAnonMarker ;          // LabelToModeMap
     // SSE
     public static final String allocSSEUnamedVars       = "_" ;                         // ParseHandlerPlain - SSE token "?" - legal SPARQL
@@ -220,7 +220,7 @@ public class ARQConstants
     public static final Symbol sysCurrentDataset        = Symbol.create(systemVarNS+"dataset") ;
 
     public static final Symbol sysVarAllocRDFStar       = Symbol.create(systemVarNS+"varAllocRDFStar") ;
-    
+
     /** Context key for the dataset description (if any).
      *  See the <a href="http://www.w3.org/TR/sparql11-protocol">SPARQL protocol</a>.
      *  <p>
@@ -258,13 +258,20 @@ public class ARQConstants
     public static final Symbol sysVarAllocAnon          = Symbol.create(systemVarNS+"namedVarAnon") ;
 
     /** Graphs forming the default graph (List&lt;String&gt;) (Dynamic dataset) */
-    public static final Symbol symDatasetDefaultGraphs     = SystemARQ.allocSymbol("datasetDefaultGraphs") ;
+    public static final Symbol symDatasetDefaultGraphs  = SystemARQ.allocSymbol("datasetDefaultGraphs") ;
 
     /** Graphs forming the named graphs (List&lt;String&gt;) (Dynamic dataset) */
-    public static final Symbol symDatasetNamedGraphs       = SystemARQ.allocSymbol("datasetNamedGraphs") ;
+    public static final Symbol symDatasetNamedGraphs    = SystemARQ.allocSymbol("datasetNamedGraphs") ;
 
     /** Context symbol for a supplied {@link Prologue} (used for text out of result sets). */
-    public static final Symbol symPrologue                 = SystemARQ.allocSymbol("prologue");
+    public static final Symbol symPrologue              = SystemARQ.allocSymbol("prologue");
+
+    /**
+     * Internal use context symbol for an AtomicBoolean to signal that a query has been cancelled.
+     * Used by {@code QueryExecutionMain} and {@code QueryIterProcessBinding}.
+     * JENA-2141.
+     */
+    public static final Symbol symCancelQuery           = SystemARQ.allocSymbol("cancelQuery");
 
     /** Context key for making all SELECT queries have DISTINCT applied, whether stated or not */
     public static final Symbol autoDistinct             = SystemARQ.allocSymbol("autoDistinct") ;
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
index c747509..1a4857d 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryExecutionBase.java
@@ -451,9 +451,18 @@ public class QueryExecutionBase implements QueryExecution
     }
 
     class TimeoutCallback implements Runnable {
+        private final AtomicBoolean cancelSignal;
+
+        public TimeoutCallback(AtomicBoolean cancelSignal) {
+            this.cancelSignal = cancelSignal;
+        }
+
         @Override
         public void run() {
             synchronized (lockTimeout) {
+                if ( cancelSignal != null )
+                    cancelSignal.set(true);
+
                 // Abort query if and only if we are the expected callback.
                 // If the first row has appeared, and we are removing timeout1
                 // callback,
@@ -484,7 +493,7 @@ public class QueryExecutionBase implements QueryExecution
                 // So nearly not needed.
                 synchronized(lockTimeout)
                 {
-                    TimeoutCallback callback = new TimeoutCallback() ;
+                    TimeoutCallback callback = new TimeoutCallback(null) ;
                     expectedCallback.set(callback) ;
                     // Lock against calls of .abort() or of timeout1Callback.
 
@@ -548,10 +557,22 @@ public class QueryExecutionBase implements QueryExecution
             return;
         }
 
+        // JENA-2140 - the timeout can go off while building the query iterator structure.
+        // In this case, use a signal passed through the context.
+        // We don't know if getPlan().iterator() does a lot of work or not
+        // (ideally it shouldn't start executing the query but in some sub-systems
+        // it might be necessary)
+        //
+        // This applies to the time to first result because to get the first result, the
+        // queryIterator must have been built. So it does not apply for the second
+        // stage of N,-1 or N,M.
+
         if ( !isTimeoutSet(timeout1) && isTimeoutSet(timeout2) ) {
             // Case -1,N
             // Single overall timeout.
-            TimeoutCallback callback = new TimeoutCallback() ;
+            AtomicBoolean cancelSignal = new AtomicBoolean(false);
+            context.set(ARQConstants.symCancelQuery, cancelSignal);
+            TimeoutCallback callback = new TimeoutCallback(cancelSignal) ;
             expectedCallback.set(callback) ;
             timeout2Alarm = alarmClock.add(callback, timeout2) ;
             // Start the query.
@@ -566,13 +587,14 @@ public class QueryExecutionBase implements QueryExecution
         //   Whether timeout2 is set is determined by QueryIteratorTimer2
         //   Subcase 2: ! isTimeoutSet(timeout2)
         // Add timeout to first row.
-        TimeoutCallback callback = new TimeoutCallback() ;
+
+        AtomicBoolean cancelSignal = new AtomicBoolean(false);
+        context.set(ARQConstants.symCancelQuery, cancelSignal);
+
+        TimeoutCallback callback = new TimeoutCallback(cancelSignal) ;
         timeout1Alarm = alarmClock.add(callback, timeout1) ;
         expectedCallback.set(callback) ;
 
-        // We don't know if getPlan().iterator() does a lot of work or not
-        // (ideally it shouldn't start executing the query but in some sub-systems
-        // it might be necessary)
         queryIterator = getPlan().iterator() ;
 
         // Add the timeout1->timeout2 resetter wrapper.
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterProcessBinding.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterProcessBinding.java
index 7f528bf..72b1e04 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterProcessBinding.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterProcessBinding.java
@@ -19,8 +19,11 @@
 package org.apache.jena.sparql.engine.iterator ;
 
 import java.util.NoSuchElementException ;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.query.QueryCancelledException;
+import org.apache.jena.sparql.ARQConstants;
 import org.apache.jena.sparql.ARQInternalErrorException ;
 import org.apache.jena.sparql.engine.ExecutionContext ;
 import org.apache.jena.sparql.engine.QueryIterator ;
@@ -34,20 +37,28 @@ import org.apache.jena.sparql.engine.binding.Binding ;
 public abstract class QueryIterProcessBinding extends QueryIter1 {
     /** Process the binding - return null for "not accept".
      * Subclasses may return a different Binding to the argument and
-     * the result is the returned Binding.  
+     * the result is the returned Binding.
      */
     abstract public Binding accept(Binding binding) ;
 
     private Binding nextBinding ;
+    private final AtomicBoolean signalCancel ;
 
     public QueryIterProcessBinding(QueryIterator qIter, ExecutionContext context) {
         super(qIter, context) ;
         nextBinding = null ;
+        AtomicBoolean signal;
+        try {
+            signal = context.getContext().get(ARQConstants.symCancelQuery);
+        } catch(Exception ex) {
+            signal = null;
+        }
+        signalCancel = signal;
     }
 
     /**
      * Are there any more acceptable objects.
-     * 
+     *
      * @return true if there is another acceptable object.
      */
     @Override
@@ -64,6 +75,7 @@ public abstract class QueryIterProcessBinding extends QueryIter1 {
             throw new ARQInternalErrorException(Lib.className(this) + ": Null iterator") ;
 
         while (getInput().hasNext()) {
+            checkCancelled();
             // Skip forward until a binding to return is found.
             Binding input = getInput().nextBinding() ;
             Binding output = accept(input) ;
@@ -76,9 +88,16 @@ public abstract class QueryIterProcessBinding extends QueryIter1 {
         return false ;
     }
 
+    private final void checkCancelled() {
+        if ( signalCancel != null && signalCancel.get() ) {
+            this.cancel();
+            throw new QueryCancelledException();
+        }
+    }
+
     /**
      * The next acceptable object in the iterator.
-     * 
+     *
      * @return The next acceptable object.
      */
     @Override