OK, after editing a bunch of tab/space inconsistencies,
the attached iter.diff takes master/cancel_sort and inserts
the tests. (Too make sure, I made the diff, undid the changes,
applied the diff -- hooray, doesn't barf -- and checked that
it looked like the changes had been applied.)

If an alternative approach would be better, let me know.

have a good Easter

Chris


On 13 April 2017 at 16:34, Chris Dollin <[email protected]>
wrote:

> On 13 April 2017 at 14:57, Chris Dollin <[email protected]>
> wrote:
>
>> On 13 April 2017 at 11:43, Andy Seaborne <[email protected]> wrote:
>>
>>>
>>>
>>>
> It would be quicker if you could provide the content in unbroken form.
>
>
>
>> Yes.
>>
>
> There will be a delay, I seem to produce diff files that can't
> be applied. Something to do with spaces and tabs.
>
> Chris
>
> --
> "What I don't understand is this ..."   Trevor Chaplin, /The Beiderbeck
> Affair/
>
> Epimorphics Ltd, http://www.epimorphics.com
> Registered address: Court Lodge, 105 High Street, Portishead, Bristol BS20
> 6PT
> Epimorphics Ltd. is a limited company registered in England (number
> 7016688)
>



-- 
"What I don't understand is this ..."   Trevor Chaplin, /The Beiderbeck
Affair/

Epimorphics Ltd, http://www.epimorphics.com
Registered address: Court Lodge, 105 High Street, Portishead, Bristol BS20
6PT
Epimorphics Ltd. is a limited company registered in England (number 7016688)
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterSort.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterSort.java
index 173da34..a489aa1 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterSort.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterSort.java
@@ -92,6 +92,7 @@ public class QueryIterSort extends QueryIterPlainWrapper {
             // iterator in a try/finally block, and thus will call
             // close() themselves.
             catch (QueryCancelledException e) {
+               QueryIterSort.this.close();
                 close();
                 throw e;
             }
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTopN.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTopN.java
index a9e2f65..b66e036 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTopN.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTopN.java
@@ -29,6 +29,7 @@ import java.util.PriorityQueue ;
 import org.apache.jena.atlas.iterator.Iter ;
 import org.apache.jena.atlas.iterator.IteratorDelayedInitialization ;
 import org.apache.jena.query.Query ;
+import org.apache.jena.query.QueryCancelledException;
 import org.apache.jena.query.QueryExecException ;
 import org.apache.jena.query.SortCondition ;
 import org.apache.jena.sparql.engine.ExecutionContext ;
@@ -93,22 +94,29 @@ public class QueryIterTopN extends QueryIterPlainWrapper
         return new IteratorDelayedInitialization<Binding>() {
             @Override
             protected Iterator<Binding> initializeIterator() {
-                while ( qIter.hasNext() ) {
-                    Binding binding = qIter.next() ;
-                    if ( heap.size() < limit )
-                        add(binding) ;
-                    else {
-                        Binding currentMaxLeastN = heap.peek() ;
-                        if ( comparator.compare(binding, currentMaxLeastN) < 0 
)
-                            add(binding) ;
-                    }
-                }
-                qIter.close() ;
-                Binding[] y = heap.toArray(new Binding[]{}) ;
-                heap = null ;
-                Arrays.sort(y, comparator) ;
-                return asList(y).iterator() ;
-            }
+               try {
+                       while ( qIter.hasNext() ) {
+                           Binding binding = qIter.next() ;
+                           if ( heap.size() < limit )
+                               add(binding) ;
+                           else {
+                               Binding currentMaxLeastN = heap.peek() ;
+                               if ( comparator.compare(binding, 
currentMaxLeastN) < 0 )
+                                   add(binding) ;
+                           }
+                       }
+                       qIter.close() ;
+                       Binding[] y = heap.toArray(new Binding[]{}) ;
+                       heap = null ;
+                       Arrays.sort(y, comparator) ;
+                       return asList(y).iterator() ;
+                   }
+               catch (QueryCancelledException e) {
+                       QueryIterTopN.this.close();
+                       this.close();
+                       throw e;
+               }
+               }
         } ;
     }
 
diff --git 
a/jena-arq/src/test/java/org/apache/jena/sparql/engine/iterator/TestQueryIterSort.java
 
b/jena-arq/src/test/java/org/apache/jena/sparql/engine/iterator/TestQueryIterSort.java
index dd1b08c..c4ec1ce 100644
--- 
a/jena-arq/src/test/java/org/apache/jena/sparql/engine/iterator/TestQueryIterSort.java
+++ 
b/jena-arq/src/test/java/org/apache/jena/sparql/engine/iterator/TestQueryIterSort.java
@@ -18,9 +18,7 @@
 
 package org.apache.jena.sparql.engine.iterator;
 
-import static org.junit.Assert.assertEquals ;
-import static org.junit.Assert.assertNotNull ;
-import static org.junit.Assert.assertTrue ;
+import static org.junit.Assert.*;
 
 import java.util.ArrayList ;
 import java.util.Iterator ;
@@ -135,6 +133,37 @@ public class TestQueryIterSort {
         assertEquals(0, DataBagExaminer.countTemporaryFiles(qIter.db)) ;
     }
     
+    @Test public void testCloseClosesSourceIterator() {
+       Context context = new Context() ;
+       ExecutionContext ec = new ExecutionContext(context, (Graph) null, 
(DatasetGraph) null, (OpExecutorFactory) null);
+       QueryIterSort qis = new QueryIterSort(iterator, comparator, ec);
+       qis.close();
+       assertTrue("source iterator should have been closed", 
iterator.isClosed());
+    }
+
+        @Test public void testExhaustionClosesSourceIterator() {
+               iterator.setCallback(new Callback()
+                       { @Override public void call() { /* do nothing */ }
+               });
+               Context context = new Context() ;
+               ExecutionContext ec = new ExecutionContext(context, (Graph) 
null, (DatasetGraph) null, (OpExecutorFactory) null);
+               QueryIterSort qis = new QueryIterSort(iterator, comparator, ec);
+               while (qis.hasNext()) qis.next();
+               assertTrue("source iterator should have been closed", 
iterator.isClosed());
+       }
+
+        @Test public void testCancelClosesSourceIterator() {
+               Context context = new Context() ;
+               ExecutionContext ec = new ExecutionContext(context, (Graph) 
null, (DatasetGraph) null, (OpExecutorFactory) null);
+               QueryIterSort qis = new QueryIterSort(iterator, comparator, ec);
+               try {
+                       while (qis.hasNext()) qis.next();
+                       fail("query should have been cancelled by trigger");
+               } catch (QueryCancelledException q) {
+                       assertTrue("source iterator should have been closed", 
iterator.isClosed());
+               }
+       }
+
     @Test
     public void testCleanAfterExhaustion()
     {
@@ -248,6 +277,32 @@ public class TestQueryIterSort {
         assertEquals(0, DataBagExaminer.countTemporaryFiles(qIter.db)) ;
     }
 
+    @Test public void testTopNCloseClosesSource() {
+
+       long numItems = 3;
+       boolean distinct = false;
+       Context context = new Context() ;
+       ExecutionContext ec = new ExecutionContext(context, (Graph) null, 
(DatasetGraph) null, (OpExecutorFactory) null);
+       QueryIterTopN tn = new QueryIterTopN(iterator, comparator, numItems, 
distinct, ec);
+       tn.close();
+       assertTrue(iterator.isClosed());
+       }
+
+       @Test public void testTopNExhaustionClosesSource() {
+
+       Callback nullCB = new Callback() { @Override public void call() {} };
+       iterator.setCallback(nullCB);
+
+       long numItems = 3;
+       boolean distinct = false;
+       Context context = new Context() ;
+       ExecutionContext ec = new ExecutionContext(context, (Graph) null, 
(DatasetGraph) null, (OpExecutorFactory) null);
+       QueryIterTopN tn = new QueryIterTopN(iterator, comparator, numItems, 
distinct, ec);
+       while (tn.hasNext()) tn.next();
+       assertTrue(iterator.isClosed());
+    }
+
+
     private Binding randomBinding(Var[] vars)
     {
         BindingMap binding = BindingFactory.create();
@@ -279,13 +334,14 @@ public class TestQueryIterSort {
     }
     
 
-    private class CallbackIterator implements QueryIterator
+    private static class CallbackIterator implements QueryIterator
     {
         int elementsReturned = 0 ;
         Callback callback ;
         int trigger ;
         Iterator<Binding> delegate ;
         boolean canceled = false ;
+        boolean closed = false ;
         
         public CallbackIterator(Iterator<Binding> delegate, int trigger, 
Callback callback)
         {
@@ -302,7 +358,10 @@ public class TestQueryIterSort {
         @Override
         public boolean hasNext() 
         {
-            return delegate.hasNext() ;
+               // self-closing
+               boolean has = delegate.hasNext() ;
+               if (has == false) closed = true;
+               return has ;
         }
 
         @Override
@@ -326,6 +385,10 @@ public class TestQueryIterSort {
             return elementsReturned ;
         }
 
+        public boolean isClosed() {
+               return closed ;
+        }
+
         public boolean isCanceled() {
             return canceled ;
         }
@@ -341,7 +404,7 @@ public class TestQueryIterSort {
         public void cancel() { canceled = true ; }
         
         @Override
-        public void close() { }
+        public void close() { closed = true ; }
         
         @Override
         public void output(IndentedWriter out, SerializationContext sCxt) { 
throw new ARQNotImplemented() ; }
@@ -354,7 +417,7 @@ public class TestQueryIterSort {
 
     }
 
-    private interface Callback
+    public interface Callback
     {
         public void call() ;
     }

Reply via email to