You cannot mix transactional and non-transactional usage together and TDB will explicitly prevent that
Each dataset instance needs to explicitly begin a transaction Rob On 13/09/2017 10:01, "George News" <[email protected]> wrote: On 2017-09-12 12:05, Rob Vesse wrote: > I think that Andy’s response was perhaps not comprehensive enough. > > As he explained a storage area supports any number of read > transactions and at the most one write transaction. The number of > active transactions is centrally managed within the JVM and scoped by > the storage area. > > However, each dataset instance you create has its own isolated > transactional view onto this storage. This allows for transactions to > interleave safely, that point at which the transaction begins will > dictate what view each dataset instance gets. I have being doing some test with different dataset instances and the expected behaviour from your answer (at least what I understood) is not working. Dataset d = TDBFactory.createDataset(tripleStorePath); Dataset d1 = TDBFactory.createDataset(tripleStorePath); Dataset d2 = TDBFactory.createDataset(tripleStorePath); d.begin(ReadWrite.READ); MultiUnion union = new MultiUnion(); union.addGraph(d1.getNameModel("whatever1").getGraph()); union.addGraph(d1.getNameModel("whatever2").getGraph()); Model m1 = ModelFactory.createModelForGraph(union); union = new MultiUnion(); union.addGraph(d2.getNameModel("whatever3").getGraph()); union.addGraph(d2.getNameModel("whatever4").getGraph()); Model m2 = ModelFactory.createModelForGraph(union); Model m3 = ModelFactory.createUnion(m1, m2); d.end(); In my case I get an exception not in transaction when creating m3. Is this the expected? From my understanding of your explanation there shouldn't be any problem. org.apache.jena.tdb.transaction.TDBTransactionException: Not in a transaction at org.apache.jena.tdb.transaction.DatasetGraphTransaction.get(DatasetGraphTransaction.java:117) ~[jena-tdb-3.2.0.jar:3.2.0] at org.apache.jena.tdb.transaction.DatasetGraphTransaction.getDatasetGraphToQuery(DatasetGraphTransaction.java:80) ~[jena-tdb-3.2.0.jar:3.2.0] at org.apache.jena.tdb.store.GraphTxnTDB.getDatasetGraphTDB(GraphTxnTDB.java:49) ~[jena-tdb-3.2.0.jar:3.2.0] at org.apache.jena.tdb.store.GraphTDB.createPrefixMapping(GraphTDB.java:80) ~[jena-tdb-3.2.0.jar:3.2.0] at org.apache.jena.graph.impl.GraphBase.getPrefixMapping(GraphBase.java:165) ~[jena-core-3.2.0.jar:3.2.0] at org.apache.jena.graph.compose.Dyadic.<init>(Dyadic.java:44) ~[jena-core-3.2.0.jar:3.2.0] at org.apache.jena.graph.compose.Union.<init>(Union.java:37) ~[jena-core-3.2.0.jar:3.2.0] at org.apache.jena.rdf.model.ModelFactory.createUnion(ModelFactory.java:309) ~[jena-core-3.2.0.jar:3.2.0] ......... Any idea? Sorry for insisting that much in the issue :( > So for example you > could start a read transaction that is long-running, have a short > write transaction and then another read transaction. The first read > transaction is seeing the state of the database prior to the write > whereas the second read transaction would be seeing the state of the > database after the write. > > Rob > > On 12/09/2017 10:24, "George News" <[email protected]> wrote: > > On 2017-09-12 10:43, Andy Seaborne wrote: >> They are per storage area. >> >> This blocks and never prints "DONE" >> >> Location loc = Location.create("DB"); Dataset dataset1 = >> TDBFactory.createDataset(loc); Dataset dataset2 = >> TDBFactory.createDataset(loc); dataset1.begin(ReadWrite.WRITE) ; >> dataset2.begin(ReadWrite.WRITE) ; System.out.println("DONE"); >> >> but if either a READ, it will work - there and be many readers and >> one writer at a time. The readers will not see the updated by the >> writer even after the writer commits. > > I understands that but I still think they are not liked to the > storage area. If you put > > Location loc = Location.create("DB"); Dataset dataset1 = > TDBFactory.createDataset(loc); Dataset dataset2 = > TDBFactory.createDataset(loc); dataset1.begin(ReadWrite.READ) ; > System.out.println(dataset1.isInTransaction()); > System.out.println(dataset2.isInTransaction()); > dataset2.begin(ReadWrite.READ) ; System.out.println("DONE"); > > It will print true for dataset1 and false for dataset2 cases. This > means that the transaction is linked to the object Dataset and not > the real location. Or at least this is what is happening to me. > > Therefore I think this is a bug :( as the transaction READ is opened > over the same location. I haven't checked for the WRITE but I guess > it should be the same. If you write on a dataset and you have a > several transactions opened this means you will have a kind of a > counter (semaphore) and when you call the .end() you finish them. > >> >> Creating the datasets is quite cheap. It is not really creating >> everything everytime. But a statics works as well; Fuseki uses a >> static registry of datasets. >> >> (it's called "connect", "not "create" in TDB2 to make that >> clearer). >> >> Andy > > I think the static will be the way to go for me for the cleanness of > the code, as otherwise it will more complex to handle. > >> >> On 11/09/17 15:57, George News wrote: >>> Hi all, >>> >>> I'm facing an issue that I guess it was implemented that way for >>> some reason. The issue is that I thought that transactions were >>> Dataset based, not the object but the TDB or whatever database >>> you use. >>> >>> However while developing my service I have noticed that if you >>> open 2 datasets on the same TDB >>> >>> Dataset dataset1 = TDBFactory.createDataset(tripleStorePath); >>> Dataset dataset2 = TDBFactory.createDataset(tripleStorePath); >>> >>> then each dataset has it's own transaction pointer, that is, >>> read/write operations are block per object. Is that the expected >>> behaviour? Why is like this and not blocked per triple store? >>> >>> Therefore my question now goes in the direction of which is >>> better. I'm developing a webservice that is working against the >>> same triple store path. The Dataset object I create on each call >>> is link to the instance of the class (not static). Then, how >>> should I proceed? Should I create the Dataset variable as static, >>> so this way I only have one object for all? >>> >>> Thanks Regards, >>> >> > > > > > >
