Thanks Dave. Does the following code look reasonable?
OntModel ontModel = OntDocumentManager.getInstance().getOntology(ontologyURI, ontModelSpec); ontModel.enterCriticalSection(Lock.READ); try { OntModel clonedModel = ModelFactory.createOntologyModel(ontModelSpec); clonedModel.add(ontModel); return clonedModel; } finally { ontModel.leaveCriticalSection(); } On Wed, Jul 20, 2016 at 10:46 AM, Dave Reynolds <dave.e.reyno...@gmail.com> wrote: > So that's the reasoner in which case you need to lock the OntModel. > > Dave > > > On 19/07/16 17:04, Martynas Jusevičius wrote: >> >> Hey Andy, >> >> I am not sure yet what is it that I need to lock - is it the OntModel, or >> the OntDocumentManager instance, or maybe both. >> >> But here are 2 actual exceptions: >> >> java.util.ConcurrentModificationException >> at >> >> com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator.checkCME(LPTopGoalIterator.java:247) >> at >> >> com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator.hasNext(LPTopGoalIterator.java:221) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> at >> com.hp.hpl.jena.util.iterator.Map1Iterator.hasNext(Map1Iterator.java:48) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> com.hp.hpl.jena.util.iterator.Map1Iterator.hasNext(Map1Iterator.java:48) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> at >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> at >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> at >> >> org.graphity.client.filter.response.ConstructorBase.construct(ConstructorBase.java:130) >> >> >> >> >> java.util.ConcurrentModificationException: Due to closed iterator >> >> com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator.checkClosed(LPTopGoalIterator.java:256) >> >> com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator.moveForward(LPTopGoalIterator.java:95) >> >> com.hp.hpl.jena.reasoner.rulesys.impl.LPTopGoalIterator.hasNext(LPTopGoalIterator.java:222) >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> >> com.hp.hpl.jena.util.iterator.FilterIterator.hasNext(FilterIterator.java:54) >> com.hp.hpl.jena.util.iterator.Map1Iterator.hasNext(Map1Iterator.java:48) >> >> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:90) >> com.hp.hpl.jena.xmloutput.impl.Basic.writeRDFStatements(Basic.java:85) >> com.hp.hpl.jena.xmloutput.impl.Basic.writeRDFStatements(Basic.java:74) >> com.hp.hpl.jena.xmloutput.impl.Basic.writeBody(Basic.java:48) >> >> com.hp.hpl.jena.xmloutput.impl.BaseXMLWriter.writeXMLBody(BaseXMLWriter.java:492) >> com.hp.hpl.jena.xmloutput.impl.BaseXMLWriter.write(BaseXMLWriter.java:464) >> com.hp.hpl.jena.xmloutput.impl.BaseXMLWriter.write(BaseXMLWriter.java:450) >> com.hp.hpl.jena.rdf.model.impl.ModelCom.write(ModelCom.java:340) >> >> com.hp.hpl.jena.ontology.impl.OntModelImpl.writeAll(OntModelImpl.java:2650) >> >> On Tue, 19 Jul 2016 at 14:04, Andy Seaborne <a...@apache.org> wrote: >> >>> On 17/07/16 13:54, Martynas Jusevičius wrote: >>>> >>>> But then again, I cannot lock what I don't have: locks work on models, >>> >>> and >>>> >>>> I only get OntModel instance when getOntology() is called. >>>> >>>> Maybe synchronized is the solution here? >>> >>> >>> You can lock how you like - the Jena lock code is helper code, to >>> promote proper critical sections and make app writers aware that >>> concurrency matters. It is not fundamental in any way - it's normally a >>> a java ReentrantReadWriteLock with some tracking code to catch >>> programming errors. >>> >>> If you are observing actual exceptions, it would be good to get the >>> traces. The caches are based on Guava's thread safe cache code although >>> (legacy) the cache setter is outside the get-or-fill operation. From >>> reading the code, it looks like the worse that can happen is to read a >>> remote resource more than once. But it's possible I've missed what >>> happening. >>> >>> As a general system point : notional read operations that internally >>> cache should make themselves multi-thread-read safe. >>> >>> Andy >>> >>> >>>> On Sun, 17 Jul 2016 at 15:32, Martynas Jusevičius <marty...@graphity.org >>>> >>>> wrote: >>>> >>>>> Thanks Andy. >>>>> >>>>> All of our code except OntDocumentManager access uses imutable objects, >>> >>> so >>>>> >>>>> I hope to keep lock usage to an absolute minimum. Transactions look >>> >>> like an >>>>> >>>>> overkill at this point. >>>>> >>>>> So if getOntology() is a write operation, if I wrap only this piece of >>>>> code where it is called into a WRITE critical section, wouldn't that be >>>>> enough? >>>>> >>>>> I think the docs lack an explanation on which ops are read and which >>>>> are >>>>> write. >>>>> >>>>> On Sun, 17 Jul 2016 at 12:22, Andy Seaborne <a...@apache.org> wrote: >>>>> >>>>>> Better: transactions (3.1.0) >>>>>> >>>>>> http://jena.staging.apache.org/documentation/txn/transactions.html >>>>>> >>>>>> We now have a fully ACID transactional in-memory graph (TIM) as well >>>>>> as >>>>>> TDB. >>>>>> >>>>>> The "Txn" highlevel API is not in the released codebase. >>>>>> >>>>>> http://jena.staging.apache.org/documentation/txn/txn.html >>>>>> >>>>>> Planning now for transactions should make things a lot easier later. >>>>>> >>>>>> Andy >>>>>> >>>>>> On 16/07/16 16:03, Martynas Jusevičius wrote: >>>>>>> >>>>>>> On a second thought, since our code is only reading from the models, >>> >>> it >>>>>> >>>>>> is >>>>>>> >>>>>>> probably easier and safer just to clone the shared model into a >>>>>> >>>>>> per-request >>>>>>> >>>>>>> copy, and keep the code as it is. >>>>>> >>>>>> >>>>>> If the shared model is only ever read, you can share it. >>>>>> >>>>>> (getOntology isn't a read operation.) >>>>>> >>>>>>> >>>>>>> Is the following code the fastest way to do it? Is add() expensive? >>>>>>> >>>>>>> >>>>>>> OntModel ontModel = >>>>>>> OntDocumentManager.getInstance().getOntology(ontologyURI, >>> >>> ontModelSpec); >>>>>>> >>>>>>> OntModel clonedModel = >>>>>>> ModelFactory.createOntologyModel(ontModelSpec); >>>>>>> clonedModel.add(ontModel); >>>>>>> >>>>>>> >>>>>>> On Sat, Jul 16, 2016 at 3:47 PM, Martynas Jusevičius < >>>>>> >>>>>> marty...@graphity.org> >>>>>>> >>>>>>> wrote: >>>>>>>> >>>>>>>> Hey, >>>>>>>> >>>>>>>> in our webapp, all objects are created per-request, except >>>>>>>> ontologies >>>>>>>> stored in a shared OntDocumentManager, that are accessed like this: >>>>>>>> >>>>>>>> OntDocumentManager.getInstance().getOntology(ontologyURI, >>>>>> >>>>>> ontModelSpec); >>>>>>>> >>>>>>>> >>>>>>>> This has caused some ConcurrentModificationExceptions. >>>>>>>> I have read the >>>>>>>> https://jena.apache.org/documentation/notes/concurrency-howto.html >>>>>>>> document, and wanted to check if I get this right. >>>>>>>> >>>>>>>> Basically, every operation and iterator on a shared OntModel has to >>> >>> be >>>>>>>> >>>>>>>> in a critical section? Even if it's indirect and called on an >>> >>> OntClass >>>>>>>> >>>>>>>> from the OntModel: >>>>>>>> >>>>>>>> OntModel ontModel = >>>>>>>> OntDocumentManager.getInstance().getOntology(ontologyURI, >>>>>>>> ontModelSpec); >>>>>>>> ontModel.enterCriticalSection(Lock.READ); >>>>>>>> try >>>>>>>> { >>>>>>>> OntClass ontClass = >>>>>>>> ontModel.getOntClass("http://some/class"); >>>>>>>> NodeIterator it = >>> >>> ontClass.listPropertyValues(GC.supportedMode); >>>>>>>> >>>>>>>> try >>>>>>>> { >>>>>>>> while (it.next) >>>>>>>> ... >>>>>>>> } >>>>>>>> finally >>>>>>>> { >>>>>>>> it.close(); >>>>>>>> } >>>>>>>> } >>>>>>>> finally >>>>>>>> { >>>>>>>> model.leaveCriticalSection() ; >>>>>>>> } >>>>>>>> >>>>>>>> Is that correct? >>>>>>>> >>>>>>>> Martynas >>>>>>> >>>>>>> >>>>>> >>>>>> >>>> >>> >>> >> >