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.


>>      // 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
> 

Reply via email to