/* * 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.tdb.store; import java.util.ConcurrentModificationException ; import java.util.Iterator ; import org.apache.jena.atlas.junit.BaseTest ; import org.apache.jena.atlas.lib.StrUtils ; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.GraphUtil ; import org.apache.jena.graph.Triple ; import org.apache.jena.query.* ; import org.apache.jena.rdf.model.Model ; import org.apache.jena.rdf.model.RDFNode ; import org.apache.jena.rdf.model.Resource ; import org.apache.jena.rdf.model.Statement ; import org.apache.jena.sparql.core.DatasetGraph ; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.sse.Item ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderGraph ; import org.apache.jena.tdb.TDBFactory ; import org.apache.jena.util.iterator.ExtendedIterator ; import org.junit.Test ; public class TestConcurrentAccess extends BaseTest { static String data = StrUtils.strjoinNL( "(graph", " (<x> <p> 1)" , " (<x> <p> 2)" , " (<x> <p> 3)" , " (<x> <p> 4)" , " (<x> <p> 5)" , " (<x> <p> 6)" , " (<x> <p> 7)" , " (<x> <p> 8)" , " (<x> <p> 9)" , ")") ; private static Graph buildGraph() { Item item = SSE.parse(data) ; Graph g = BuilderGraph.buildGraph(item) ; return g ; } private static Dataset create() { Graph g = buildGraph() ; Dataset ds = TDBFactory.createDataset() ; GraphUtil.addInto(ds.getDefaultModel().getGraph(), g) ; return ds ; } @Test public void mrswGraph1() { Model m = create().getDefaultModel() ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listStatements(r, null, (RDFNode)null) ; assertNotNull(iter1.next()) ; ExtendedIterator<Statement> iter2 = m.listStatements(r, null, (RDFNode)null) ; assertNotNull(iter2.next()) ; for ( ; iter2.hasNext() ; ) iter2.next() ; assertNotNull(iter1.next()) ; } @Test(expected=ConcurrentModificationException.class) public void mrswGraph2() { Model m = create().getDefaultModel() ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listStatements(r, null, (RDFNode)null) ; assertNotNull(iter1.next()) ; Triple t = SSE.parseTriple("(<y> <p> 99)") ; m.getGraph().add(t) ; // Bad iter1.hasNext(); } @Test(expected=ConcurrentModificationException.class) public void mrswGraph3() { Model m = create().getDefaultModel() ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listStatements(r, null, (RDFNode)null) ; assertNotNull(iter1.next()) ; Triple t = SSE.parseTriple("(<y> <p> 99)") ; m.getGraph().delete(t) ; // Bad iter1.hasNext(); } @Test(expected=ConcurrentModificationException.class) public void mrswGraph4() { Model m = create().getDefaultModel() ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listLiteralStatements(r, null, 1) ; assertNotNull(iter1.next()) ; // and now the iterator has implicitly finished. Triple t = SSE.parseTriple("(<y> <p> 99)") ; m.getGraph().add(t) ; // Bad - modification of the dataset occurred. iter1.hasNext(); } @Test public void mrswGraph5() { Dataset d = TDBFactory.createDataset() ; Model m = d.getNamedModel("http://example") ; GraphUtil.addInto(m.getGraph(), buildGraph()) ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listStatements(r, null, (RDFNode)null) ; while(iter1.hasNext()) iter1.next(); Triple t = SSE.parseTriple("(<y> <p> 99)") ; m.getGraph().delete(t) ; iter1.hasNext() ; } @Test(expected=ConcurrentModificationException.class) public void mrswGraph6() { Dataset d = TDBFactory.createDataset() ; Model m = d.getNamedModel("http://example") ; GraphUtil.addInto(m.getGraph(), buildGraph()) ; Resource r = m.createResource("x") ; ExtendedIterator<Statement> iter1 = m.listStatements(r, null, (RDFNode)null) ; assertNotNull(iter1.next()) ; Triple t = SSE.parseTriple("(<y> <p> 99)") ; m.getGraph().delete(t) ; iter1.next() ; } @Test public void mrswSPARQL1() { Dataset ds = create(); Query query = QueryFactory.create("SELECT * { ?s ?p ?o}") ; try(QueryExecution qExec = QueryExecutionFactory.create(query, ds)) { ResultSet rs = qExec.execSelect() ; while(rs.hasNext()) rs.next(); } DatasetGraph dsg = ds.asDatasetGraph() ; Quad quad = SSE.parseQuad("(<g> <y> <p> 99)") ; dsg.add(quad) ; Iterator<Quad> iter = dsg.find() ; iter.hasNext() ; iter.next() ; } @Test(expected=ConcurrentModificationException.class) public void mrswSPARQL2() { Dataset ds = create(); DatasetGraph dsg = ds.asDatasetGraph() ; Query query = QueryFactory.create("SELECT * { ?s ?p ?o}") ; QueryExecution qExec = QueryExecutionFactory.create(query, ds) ; ResultSet rs = qExec.execSelect() ; rs.hasNext() ; rs.next(); Quad quad = SSE.parseQuad("(<g> <y> <p> 99)") ; dsg.add(quad) ; rs.hasNext() ; // <<--- Here. rs.next(); } @Test(expected=ConcurrentModificationException.class) public void mrswDataset1() { DatasetGraph dsg = create().asDatasetGraph() ; Quad quad = SSE.parseQuad("(<g> <y> <p> 99)") ; Iterator<Quad> iter = dsg.find() ; dsg.add(quad) ; // Bad - after an update. iter.hasNext() ; iter.next() ; } // More DSG tests .. }