Just to add a bit of context to Andy's point: > It needs a dataset so it makes one and puts the model in as the default graph.
This is (more or less) because SPARQL is defined as acting against datasets, not individual graphs. https://www.w3.org/TR/sparql11-query/#rdfDataset: "A SPARQL query is executed against an RDF Dataset which represents a collection of graphs." And if (as Andy pointed out is possible) the individual graph in question is a view over several datasets, that doesn't work either. There has to be a single dataset that is the basic context for SPARQL. (Even while using federation/SERVICE, there is still a single dataset against which the query is being executed.) ajs6f > On Dec 29, 2017, at 9:21 AM, Andy Seaborne <[email protected]> wrote: > > > > On 29/12/17 13:58, George News wrote: >> On 2017-12-29 14:46, Andy Seaborne wrote: >>> >>> >>> On 29/12/17 09:51, George News wrote: >>>> On 2017-12-28 18:02, dandh988 wrote: >>>>> Can you give a complete example? How are you calling MultiUnion? Are >>>>> you calling txn read on the dataset then building the union, then >>>>> calling txn write to update the graph? >>>> >>>> Let's describe a use case. >>> >>> The stack trace does not agree with the details here (and details >>> matter!) especially what dataset is because if that is a general dataset >>> built out of TDB graphs, this whole thing will not work. A complete, >>> minimal example is needed. >>> >>> A few general observations: >>> >>>> >>>> 1) I have a dataset that includes 4 named graphs: G1, G2, G3, G4 >>>> 2.a) Someone initiates a sparql request and the internal procedure >>>> followed is: >>>> return Txn.calculateRead(dataset, () -> { >>>> // Create multiunion of 3 namegraphs >>>> MultiUnion union = new MultiUnion(); >>>> union.addGraph(dataset.getNamedModel("G1").getGraph()); >>>> union.addGraph(dataset.getNamedModel("G2").getGraph()); >>>> union.addGraph(dataset.getNamedModel("G4").getGraph()); >>> >>> This can be done in SPARQL: >>> >>> either UNION or >>> >>> SELECT >>> FROM <G1> >>> FROM <G2> >>> FROM <G4> >>> WHERE { ... } >>> >>> (copy the query object and modify it). >>> >>> and TDB will handle it better. >>> >>>> >>>> Model m = ModelFactory.createModelForGraph(union); >>> >>> You are not querying the TDB dataset if you pass a model to >>> QueryExecutionFactory.create. It has to create a dataset (a general >>> purpose one) for the query. >> But if the model is created from graphs/models on a dataset, isn't it >> the same? At the end the models are a reference to ones in the dataset. > > Not the same and the model is not a reference into a dataset. > > QueryExecutionFactory.create is given a model, here a composite one, could be > a model without a datasets, could be a model over many datasets. It can't > know what the structure is, model is an interface. > > It needs a dataset so it makes one and puts the model in as the default graph. > >>>> // Launch Sparql query on it >>>> try (QueryExecution qExec = QueryExecutionFactory.create(query, >>>> m)) { >>>> return ResultSetFactory.copyResults(qExec.execSelect()) >>>> } >>>> }); >>>> >>>> 2.b) Someone initiates a sparql request and the internal procedure >>>> followed is: >>>> return Txn.calculateRead(dataset, () -> { >>>> // Create multiunion of 2 namegraphs >>>> // This code in in a function >>>> MultiUnion union = new MultiUnion(); >>>> union.addGraph(dataset.getNamedModel("G1").getGraph()); >>>> union.addGraph(dataset.getNamedModel("G2").getGraph()); >>>> Model m1 = ModelFactory.createModelForGraph(union); >>>> >>>> // Retrieve namegraph G3 >>>> // This code in in a function >>>> Model m2 = dataset.getNamedModel("G3"); >>>> >>>> Model m = ModelFactory.createUnion(m2, m1); >>>> >>>> // Launch Sparql query on it >>>> try (QueryExecution qExec = QueryExecutionFactory.create(query, >>>> m)) { >>>> return ResultSetFactory.copyResults(qExec.execSelect()) >>>> } >>>> }); >>>> >>>> >>>> 3) Someone initiaties a write in G2 >>>> // m stores the new entity model >>>> Model m; >>>> Txn.executeWrite(dataset, () -> { >>>> dataset.getNamedModel("G2").add(m); >>>> }); >>>> >>>> >>>> >>>> If either version of 2), and 3) are not done in parallel there is no >>>> problem and everything is executed correctly. >>>> >>>> The problem arise when 2.a) or 2.b) is run, and before ending someone >>>> tries to perform 3). Then I get the FileException("In the middle of an >>>> alloc-write"). >>>> >>>> Do you have an idea on how to avoid this? How can I handle >>>> transactions in this model? >>>> >>>> >>>> I was thinking on creating a global mutex so if any action is being >>>> performed over the dataset, then the rest would be blocked. The >>>> problem here is that the code is part of a webservice and then if the >>>> read/write operation lasts long, I will get a timeout that will close >>>> the connection. >>>> >>>> The other option is to disable writing while someone is reading. The >>>> main problem here is how to properly reschedule writings not to have a >>>> big queue. >>>> >>>> Any help is more than welcome. I don't know what else to do to solve >>>> this is issue, and the problem is making the service unusable :( >>>> >>>> Thanks a lot for the great help you are all offering. >>>> Jorge >>>
