[ 
https://issues.apache.org/jira/browse/JENA-399?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13584659#comment-13584659
 ] 

Rob Vesse commented on JENA-399:
--------------------------------

I may still refactor the code slightly to provide a convenience method that can 
check the prepared state and call prepare() if necessary in a single step so I 
would prefer to leave reopen for the time being.

prepare() needs to be synchronized because prepare() is the method that 
actually results in the underlying rule engines running and the inferences 
being produced.  Once prepare() has happened unless changes are made to the 
graph it should not be needed again i.e. it is an infrequent initialization 
step that gets called when the first query starts to run.
                
> Concurrent execution of SPARQL CONSTRUCT statements against the same 
> Inference Model leads to a ConcurrentModificationException
> -------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: JENA-399
>                 URL: https://issues.apache.org/jira/browse/JENA-399
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: ARQ, Reasoners
>    Affects Versions: Jena 2.10.0
>            Reporter: Stephen Owens
>            Assignee: Rob Vesse
>              Labels: InfModel, multi-threading, race-condition
>         Attachments: JenaReadLockFailureTest.java
>
>
> Read lock seems to be insufficient for a construct SPARQL query against a 
> model in a multi-threaded situation. See the attached test case for details. 
> The ConcurrentModificationException is thrown from: 
> LPTopGoalIterator.checkClosed
>  in com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator
> Here is a stack trace that shows a path from QueryExecutionBase.
> execConstruct() to LPBRuleEngine.checkSafeToUpdate():
> LPBRuleEngine.checkSafeToUpdate() line: 223    
> LPBRuleEngine.deleteAllRules() line: 155    
> RDFSRuleInfGraph(FBRuleInfGraph).prepare() line: 460    
> RDFSRuleInfGraph(FBRuleInfGraph).findWithContinuation(TriplePattern, Finder) 
> line: 573    
> RDFSRuleInfGraph(FBRuleInfGraph).graphBaseFind(Node, Node, Node) line: 605    
> RDFSRuleInfGraph(GraphBase).find(Node, Node, Node) line: 287    
> QueryIterTriplePattern$TripleMapper.<init>(Binding, Triple, ExecutionContext) 
> line: 80    
> QueryIterTriplePattern.nextStage(Binding) line: 53    
> QueryIterTriplePattern(QueryIterRepeatApply).makeNextStage() line: 115    
> QueryIterTriplePattern(QueryIterRepeatApply).hasNextBinding() line: 67    
> QueryIterTriplePattern(QueryIteratorBase).hasNext() line: 113    
> QueryIterBlockTriples.hasNextBinding() line: 64    
> QueryIterBlockTriples(QueryIteratorBase).hasNext() line: 113    
> QueryIterOptionalIndex(QueryIterRepeatApply).makeNextStage() line: 108    
> QueryIterOptionalIndex(QueryIterRepeatApply).hasNextBinding() line: 67    
> QueryIterOptionalIndex(QueryIteratorBase).hasNext() line: 113    
> QueryIteratorCheck(QueryIteratorWrapper).hasNextBinding() line: 40    
> QueryIteratorCheck(QueryIteratorBase).hasNext() line: 113    
> QueryIteratorCloseable(QueryIteratorWrapper).hasNextBinding() line: 40    
> QueryIteratorCloseable(QueryIteratorBase).hasNext() line: 113    
> Iter$5.hasNext() line: 335    
> QueryExecutionBase.execConstruct(Model) line: 225    
> QueryExecutionBase.execConstruct() line: 201    
> This is a problem because LPBRuleEngine.checkSafeToUpdate() closes all 
> LPTopGoalIterator iterators, some of which are in the middle of processing:
>     public void checkSafeToUpdate() {
>         if (!activeInterpreters.isEmpty()) {
>             ArrayList<LPInterpreterContext> toClose = new 
> ArrayList<LPInterpreterContext>();
>             for (Iterator<LPInterpreter> i = activeInterpreters.iterator(); 
> i.hasNext(); ) {
>                 LPInterpreter interpreter = i.next();
>                 if (interpreter.getContext() instanceof LPTopGoalIterator) {
>                     toClose.add(interpreter.getContext());
>                 }
>             }
>             for (Iterator<LPInterpreterContext> i = toClose.iterator(); 
> i.hasNext(); ) {
>                 ((LPTopGoalIterator)i.next()).close();
>             }
>         }
>     }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to