Hi Minto Created CLEREZZA-745 describing this issue and provided a fix with revision 1457660 [2]. You will need to port the fix to your "scalable" version (CLEREZZA-736). While I do have adapted the MultiThreadedSingleTdbDatasetTest to explicitly validate your usage scenario it would still be nice if you could validate the fix against your usage scenario
best Rupert [1] https://issues.apache.org/jira/browse/CLEREZZA-745 [2] http://svn.apache.org/r1457660 On Thu, Mar 14, 2013 at 2:43 PM, Andy Seaborne <[email protected]> wrote: > On 14/03/13 09:39, Minto van der Sluis wrote: >> >> Rupert, >> >> Thanks for the additional explanation. >> >> Regards, >> >> Minto >> >> Op 14-3-2013 10:31, Rupert Westenthaler schreef: >>> >>> Hi Minto >>> >>> I am traveling this week and do not have time to work on this until >>> the weekend but I will have a look into this. >>> >>> Let me try to explain my concern again and make it more clear: >>> >>> The Jena TDB named graphs are hold in a single quad store table (SPOC >>> - Subject Predicate Object Context). On the Clerezza side you have a >>> TripleCollections (SPO) with a name (C). What that means is that all >>> Clerezza TripleCollections provided by the same >>> SingleTdbDatasetTcProvider do share the same SPOC table. meaning that >>> a change of any of those TripleCollections will cause a modification >>> in the Jena TDB Backend. This means that Iterators of all >>> TripleCollections need to make a ReadLock on the SPOC table (and not >>> only on the SPO section represented by the TripleCollection). >>> >>> While Clerezza allows to build a LockableMGraphWrapper over an MGrpah >>> this is not sufficient for the SingleTdbDatasetTcProvider as this will >>> only protect the SPO section and not the SPOC table used by the >>> backend. So changes in other graphs - or the creation of a new graph - >>> are still possible and will cause ConcurrentModificationExceptions as >>> reported. >>> >>> To solve this issue one needs to ensure that a single ReadWrite lock >>> is used for all TripleCollections provided by the >>> SingleTdbDatasetTcProvider as this will allow users to lock the whole >>> SPOC table of the backend when they perform operations on the Clerezza >>> TripleCollections. > > > A TDB dataset provides a single Lock you can reuse/wrap so all the graph > locks are related when needed. The GraphTDB.getLock() is the dataset lock. > > Transactions would be better. Better concurrency (concurrent writer and > multiple readers). > > Andy > > >>> >>> best >>> Rupert >>> >>> >>> On Thu, Mar 14, 2013 at 9:50 AM, Minto van der Sluis <[email protected]> >>> wrote: >>>> >>>> Hi, >>>> >>>> Half of what the 2 of you write is not very clear to me. Probably due to >>>> being a novice when it comes to Clerezza internals. >>>> >>>> Maybe I will start with giving CLEREZZA-726 another try and then check >>>> if I still get these exceptions. >>>> >>>> Regard, >>>> >>>> Minto >>>> >>>> Op 13-3-2013 18:35, Reto Bachmann-Gmür schreef: >>>>> >>>>> On Wed, Mar 13, 2013 at 6:04 PM, Rupert Westenthaler < >>>>> [email protected]> wrote: >>>>> >>>>>> Hi, >>>>>> >>>>>> I think that this is cased by the fact that if you create a >>>>>> LockableMGraph over MGraphs provided by the SingleTdbDatasetTcProvider >>>>>> you end up in a situation where you have multiple ReadWrite Locks on >>>>>> the same quad store (the Jena TDB dataset). This means that acquiring >>>>>> a write lock on one MGraph will not prohibit changes in other graphs - >>>>>> or the creation of new graphs. Because of that you will end up with >>>>>> ConcurrentModificationException when using iterators over triples >>>>>> (such as going over SPARQL results). >>>>>> >>>>> True. But where is the graph locked in the first place? It should >>>>> aquire a >>>>> lock before iterating though the graph, does this happen? >>>>> >>>>> cheers, >>>>> reto >>>>> >>>>>> The solution would be to >>>>>> >>>>>> * create a single ReadWirte lock for the SingleTdbDatasetTcProvider >>>>>> * replace all synchronized(dataset){..} block with read/wirte locks >>>>>> * all methods returning MGraphs need to return LockableMGraph >>>>>> instances that do use the ReadWrite lock used by the >>>>>> SingleTdbDatasetTcProvider >>>>>> * users would than need to use the LockableMGraph instance provided by >>>>>> the provider and NOT wrap those with an other LockableMGraph instance >>>>>> (e.g. the LockableMGraphWrapper). >>>>>> >>>>>> best >>>>>> Rupert >>>>>> >>>>>> >>>>>> On Wed, Mar 13, 2013 at 5:31 PM, Minto van der Sluis <[email protected]> >>>>>> wrote: >>>>>>> >>>>>>> Hi Folks, >>>>>>> >>>>>>> I ran into an issue is both the existing SingleTdbDatasetTcProvider >>>>>>> and >>>>>>> my customized version (see CLEREZZA-736). >>>>>>> >>>>>>> How to reproduce: >>>>>>> 1) Have some process constantly inject new named graphs (I had a >>>>>>> process >>>>>>> injecting 1000 named graphs) >>>>>>> 2) perform a query while 1 is still running. I used the following >>>>>>> query: >>>>>>> >>>>>>> SELECT ?graphName WHERE { GRAPH ?graphName {} } LIMIT 10 >>>>>>> OFFSET 0 >>>>>>> >>>>>>> 3) repeat step 2 a number of times (since the error does not always >>>>>> >>>>>> occur) >>>>>>> >>>>>>> This results in a ConcurrentModificationException (see stacktrace >>>>>>> below). I am not sure whether this is a Clerezza or Jena issue. >>>>>>> >>>>>>> Anyone an idea what is causing this? Or more importantly how to fix >>>>>>> it? >>>>>>> >>>>>>> Should I create a Jira issue for this? >>>>>>> >>>>>>> Regards, >>>>>>> >>>>>>> -- >>>>>>> ir. ing. Minto van der Sluis >>>>>>> Software innovator / renovator >>>>>>> Xup BV >>>>>>> >>>>>>> >>>>>>> Stacktrace: >>>>>>> java.util.ConcurrentModificationException: Iterator: started at 7103, >>>>>> >>>>>> now 7105 >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.tdb.sys.DatasetControlMRSW.policyError(DatasetControlMRSW.java:157) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.tdb.sys.DatasetControlMRSW.access$000(DatasetControlMRSW.java:32) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.tdb.sys.DatasetControlMRSW$IteratorCheckNotConcurrent.checkCourrentModification(DatasetControlMRSW.java:110) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.tdb.sys.DatasetControlMRSW$IteratorCheckNotConcurrent.hasNext(DatasetControlMRSW.java:118) >>>>>>> >>>>>>> at org.openjena.atlas.iterator.Iter$4.hasNext(Iter.java:295) >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.tdb.store.GraphTDBBase$ProjectQuadsToTriples.hasNext(GraphTDBBase.java:173) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:76) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.jena.storage.JenaGraphAdaptor$1.hasNext(JenaGraphAdaptor.java:106) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.core.impl.AbstractTripleCollection$1.hasNext(AbstractTripleCollection.java:78) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.core.access.LockingIterator.hasNext(LockingIterator.java:47) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.jena.facade.JenaGraph$1.hasNext(JenaGraph.java:95) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.util.iterator.WrappedIterator.hasNext(WrappedIterator.java:76) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterTriplePattern$TripleMapper.hasNextBinding(QueryIterTriplePattern.java:151) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterRepeatApply.hasNextBinding(QueryIterRepeatApply.java:79) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterBlockTriples.hasNextBinding(QueryIterBlockTriples.java:64) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.main.iterator.QueryIterGraph$QueryIterGraphInner.hasNextBinding(QueryIterGraph.java:123) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterRepeatApply.hasNextBinding(QueryIterRepeatApply.java:79) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterConvert.hasNextBinding(QueryIterConvert.java:59) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIterSlice.hasNextBinding(QueryIterSlice.java:76) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:40) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:40) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:112) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> com.hp.hpl.jena.sparql.engine.ResultSetStream.hasNext(ResultSetStream.java:72) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.jena.sparql.ResultSetWrapper.<init>(ResultSetWrapper.java:39) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.jena.sparql.JenaSparqlEngine.execute(JenaSparqlEngine.java:68) >>>>>>> >>>>>>> at >>>>>> >>>>>> >>>>>> org.apache.clerezza.rdf.core.access.TcManager.executeSparqlQuery(TcManager.java:272) >>>>>>> >>>>>>> ... >>>>>>> >>>>>> >>>>>> -- >>>>>> | Rupert Westenthaler [email protected] >>>>>> | Bodenlehenstraße 11 ++43-699-11108907 >>>>>> | A-5500 Bischofshofen >>>>>> >>>> >>>> -- >>>> ir. ing. Minto van der Sluis >>>> Software innovator / renovator >>>> Xup BV >>>> >>>> Mobiel: +31 (0) 626 014541 >>>> >>> >>> >>> -- >>> | Rupert Westenthaler [email protected] >>> | Bodenlehenstraße 11 ++43-699-11108907 >>> | A-5500 Bischofshofen >>> >>> >> >> > -- | Rupert Westenthaler [email protected] | Bodenlehenstraße 11 ++43-699-11108907 | A-5500 Bischofshofen
