You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by cl...@apache.org on 2015/05/10 15:03:31 UTC

[02/50] [abbrv] jena git commit: JENA-904: Fix for LPBRuleEngine leaking activeInterpreters

JENA-904: Fix for LPBRuleEngine leaking activeInterpreters


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/4edc6d38
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/4edc6d38
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/4edc6d38

Branch: refs/heads/add-contract-tests
Commit: 4edc6d38613970894165565000f9d1f1a50a6e4c
Parents: 84d0615
Author: Andy Seaborne <an...@apache.org>
Authored: Fri May 1 12:56:24 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Fri May 1 12:56:24 2015 +0100

----------------------------------------------------------------------
 .../rulesys/impl/ConsumerChoicePointFrame.java  |  11 ++
 .../jena/reasoner/rulesys/impl/FrameObject.java |   5 +-
 .../reasoner/rulesys/impl/LPInterpreter.java    |   3 +-
 .../rulesys/impl/LPTopGoalIterator.java         |   1 +
 .../rulesys/impl/TopLevelTripleMatchFrame.java  |   2 +
 .../reasoner/rulesys/impl/TripleMatchFrame.java |   1 +
 .../rulesys/impl/TestLPBRuleEngineLeak.java     | 171 +++++++++++++++++++
 .../jena/reasoner/rulesys/test/TestPackage.java |   4 +
 8 files changed, 196 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/ConsumerChoicePointFrame.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/ConsumerChoicePointFrame.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/ConsumerChoicePointFrame.java
index e0d0b85..a1c2c26 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/ConsumerChoicePointFrame.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/ConsumerChoicePointFrame.java
@@ -161,6 +161,17 @@ public class ConsumerChoicePointFrame extends GenericTripleMatchFrame
         context.setReady(this);
     }
     
+    @Override
+    public void close() {    	
+    	super.close();
+    	if (generator != null && generator.interpreter != null) {
+    		generator.interpreter.close();
+    		// .. but NOT 
+    		//generator.setComplete();
+    		// as it seems to cause other tests to fail
+    	}
+    }
+    
     /**
      * Notify that this consumer choice point has finished consuming all
      * the results of a closed generator.

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/FrameObject.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/FrameObject.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/FrameObject.java
index 39ccc52..4128d36 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/FrameObject.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/FrameObject.java
@@ -54,7 +54,10 @@ public class FrameObject {
      * Close the frame actively. This frees any internal resources, frees this frame and
      * frees the frame to which this is linked.
      */
-    public void close() {
+    public void close() {  
+    	if (link != null) {
+    		link.close();
+    	}
     }
     
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPInterpreter.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPInterpreter.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPInterpreter.java
index 3edbb6d..fee6c97 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPInterpreter.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPInterpreter.java
@@ -164,8 +164,9 @@ public class LPInterpreter {
      */
     public void close() {
         isComplete = true;
-        engine.detach(this);
         if (cpFrame != null) cpFrame.close();
+        engine.detach(this);
+        
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPTopGoalIterator.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPTopGoalIterator.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPTopGoalIterator.java
index cb14070..d4d471b 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPTopGoalIterator.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/LPTopGoalIterator.java
@@ -197,6 +197,7 @@ public class LPTopGoalIterator implements ClosableIterator<Triple>, LPInterprete
 
                     // Check for any dangling generators which are complete
                     interpreter.getEngine().checkForCompletions();
+                    interpreter.close();
                     // Close this top goal
                     lookAhead = null;
                     //LogFactory.getLog( getClass() ).debug( "Nulling and closing LPTopGoalIterator " + interpreter );

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TopLevelTripleMatchFrame.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TopLevelTripleMatchFrame.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TopLevelTripleMatchFrame.java
index 80a718d..0caf8b2 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TopLevelTripleMatchFrame.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TopLevelTripleMatchFrame.java
@@ -66,6 +66,8 @@ public class TopLevelTripleMatchFrame extends GenericChoiceFrame {
     @Override
     public void close() {
         if (matchIterator != null) matchIterator.close();
+        super.close();
+        
     }
         
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TripleMatchFrame.java
----------------------------------------------------------------------
diff --git a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TripleMatchFrame.java b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TripleMatchFrame.java
index 8d4891d..74b1a1b 100644
--- a/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TripleMatchFrame.java
+++ b/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/impl/TripleMatchFrame.java
@@ -73,6 +73,7 @@ public class TripleMatchFrame extends GenericTripleMatchFrame {
      */
     @Override public void close() {
         if (matchIterator != null) matchIterator.close();
+        super.close();
     }
     
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngineLeak.java
----------------------------------------------------------------------
diff --git a/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngineLeak.java b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngineLeak.java
new file mode 100644
index 0000000..58e0afb
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/impl/TestLPBRuleEngineLeak.java
@@ -0,0 +1,171 @@
+/*
+ * 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.jena.reasoner.rulesys.impl;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.junit.Test;
+
+import org.apache.jena.graph.Factory;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.reasoner.rulesys.FBRuleInfGraph;
+import org.apache.jena.reasoner.rulesys.FBRuleReasoner;
+import org.apache.jena.reasoner.rulesys.Rule;
+import org.apache.jena.util.iterator.ExtendedIterator;
+import org.apache.jena.vocabulary.RDF;
+import org.apache.jena.vocabulary.RDFS;
+
+public class TestLPBRuleEngineLeak extends TestCase {
+	public static TestSuite suite() {
+		return new TestSuite(TestLPBRuleEngineLeak.class, "TestLPBRuleEngineLeak");
+	}
+
+	protected Node a = NodeFactory.createURI("a");
+	protected Node b = NodeFactory.createURI("b");
+	protected Node nohit = NodeFactory.createURI("nohit");
+	protected Node p = NodeFactory.createURI("p");
+	protected Node C1 = NodeFactory.createURI("C1");
+	protected Node C2 = NodeFactory.createURI("C2");
+	protected Node ty = RDF.Nodes.type;
+
+	public FBRuleReasoner createReasoner(List<Rule> rules) {
+		FBRuleReasoner reasoner = new FBRuleReasoner(rules);
+		reasoner.tablePredicate(RDFS.Nodes.subClassOf);
+		reasoner.tablePredicate(RDF.Nodes.type);
+		reasoner.tablePredicate(p);
+		return reasoner;
+	}
+
+	@Test
+	public void testNotLeakingActiveInterpreters() throws Exception {
+		Graph data = Factory.createGraphMem();
+		data.add(new Triple(a, ty, C1));
+		data.add(new Triple(b, ty, C1));
+		List<Rule> rules = Rule
+				.parseRules("[r1:  (?x p ?t) <- (?x rdf:type C1), makeInstance(?x, p, C2, ?t)]"
+						+ "[r2:  (?t rdf:type C2) <- (?x rdf:type C1), makeInstance(?x, p, C2, ?t)]");
+
+		FBRuleInfGraph infgraph = (FBRuleInfGraph) createReasoner(rules).bind(
+				data);
+
+		LPBRuleEngine engine = getEngineForGraph(infgraph);
+		assertEquals(0, engine.activeInterpreters.size());
+		assertEquals(0, engine.tabledGoals.size());
+
+		// we ask for a non-hit -- it works, but only because we call it.hasNext()
+		ExtendedIterator<Triple> it = infgraph.find(nohit, ty, C1);
+		assertFalse(it.hasNext());
+		it.close();
+		assertEquals(0, engine.activeInterpreters.size());
+
+		// and again.
+		// Ensure this is not cached by asking for a different triple pattern
+		ExtendedIterator<Triple> it2 = infgraph.find(nohit, ty, C2);
+		// uuups, forgot to call it.hasNext(). But .close() should tidy
+		it2.close();
+		assertEquals(0, engine.activeInterpreters.size());
+
+		
+		// OK, let's ask for something that is in the graph
+		
+		ExtendedIterator<Triple> it3 = infgraph.find(a, ty, C1);
+		assertTrue(it3.hasNext());
+		assertEquals(a, it3.next().getMatchSubject());
+		
+		// .. and what if we forget to call next() to consume b?
+		// (e.g. return from a method with the first hit)
+		
+		// this should be enough
+		it3.close();
+		// without leaks of activeInterpreters
+		assertEquals(0, engine.activeInterpreters.size());
+	}
+	
+	@Test
+	public void testTabledGoalsCacheHits() throws Exception {
+		Graph data = Factory.createGraphMem();
+		data.add(new Triple(a, ty, C1));
+		List<Rule> rules = Rule
+				.parseRules("[r1:  (?x p ?t) <- (?x rdf:type C1), makeInstance(?x, p, C2, ?t)]"
+						+ "[r2:  (?t rdf:type C2) <- (?x rdf:type C1), makeInstance(?x, p, C2, ?t)]");
+
+		FBRuleInfGraph infgraph = (FBRuleInfGraph) createReasoner(rules).bind(
+				data);
+
+		LPBRuleEngine engine = getEngineForGraph(infgraph);
+		assertEquals(0, engine.activeInterpreters.size());
+		assertEquals(0, engine.tabledGoals.size());
+
+		ExtendedIterator<Triple> it = infgraph.find(a, ty, C1);
+		while (it.hasNext()) {
+			it.next();
+			// FIXME: Why do I need to consume all from the iterator
+			// to avoid leaking activeInterpreters? Calling .close()
+			// below should have been enough.
+		}
+		it.close();
+		// how many were cached
+		assertEquals(1, engine.tabledGoals.size());
+		// and no leaks of activeInterpreters
+		assertEquals(0, engine.activeInterpreters.size());
+
+		// Now ask again:
+		it = infgraph.find(a, ty, C1);
+		while (it.hasNext()) {
+			it.next();
+		}
+		it.close();
+		// if it was a cache hit, no change here:
+		assertEquals(1, engine.tabledGoals.size());
+		assertEquals(0, engine.activeInterpreters.size());
+	}
+
+	/**
+	 * Use introspection to get to the LPBRuleEngine.
+	 * <p>
+	 * We are crossing package boundaries and therefore this test would always
+	 * be in the wrong package for either FBRuleInfGraph or LPBRuleEngine.
+	 * <p>
+	 * <strong>This method should only be used for test purposes.</strong>
+	 * 
+	 * @param infgraph
+	 * @return
+	 * @throws SecurityException
+	 * @throws NoSuchFieldException
+	 * @throws IllegalArgumentException
+	 * @throws IllegalAccessException
+	 */
+	private LPBRuleEngine getEngineForGraph(FBRuleInfGraph infgraph)
+			throws NoSuchFieldException, SecurityException,
+			IllegalArgumentException, IllegalAccessException {
+		Field bEngine = FBRuleInfGraph.class.getDeclaredField("bEngine");
+		bEngine.setAccessible(true);
+		LPBRuleEngine engine = (LPBRuleEngine) bEngine.get(infgraph);
+		return engine;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/4edc6d38/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/test/TestPackage.java
----------------------------------------------------------------------
diff --git a/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/test/TestPackage.java b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/test/TestPackage.java
index af51f6d..1a25ae7 100755
--- a/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/test/TestPackage.java
+++ b/jena-core/src/test/java/org/apache/jena/reasoner/rulesys/test/TestPackage.java
@@ -20,9 +20,12 @@ package org.apache.jena.reasoner.rulesys.test;
 
 
 import junit.framework.TestSuite ;
+
 import org.slf4j.Logger ;
 import org.slf4j.LoggerFactory ;
 
+import org.apache.jena.reasoner.rulesys.impl.TestLPBRuleEngineLeak;
+
 /**
  * Aggregate tester that runs all the test associated with the rulesys package.
  */
@@ -49,6 +52,7 @@ public class TestPackage extends TestSuite {
         addTest( "TestGenericRules", TestGenericRules.suite() );
         addTest( "TestRETE", TestRETE.suite() );
         addTest( TestSetRules.suite() );
+        addTest( TestLPBRuleEngineLeak.suite() );
         addTest( "OWLRuleUnitTests", OWLUnitTest.suite() );
         addTest( "TestBugs", TestBugs.suite() );
         addTest( "TestOWLMisc", TestOWLMisc.suite() );