Github user afs commented on a diff in the pull request: https://github.com/apache/jena/pull/336#discussion_r159746359 --- Diff: jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java --- @@ -146,25 +162,84 @@ private void _begin(ReadWrite readWrite) { } /** Called transaction start code at most once per transaction. */ - private void startTransaction(ReadWrite mode) { - transactionLock.enterCriticalSection(mode.equals(READ)); // get the dataset write lock, if needed. - transactionType(mode); + private void startTransaction(TxnType txnType, ReadWrite mode) { + transactionLock.enterCriticalSection(mode.equals(ReadWrite.READ)); // get the dataset write lock, if needed. + transactionType.set(txnType); + transactionMode(mode); isInTransaction(true); } /** Called transaction ending code at most once per transaction. */ private void finishTransaction() { isInTransaction.remove(); transactionType.remove(); + transactionMode.remove(); version.remove(); transactionLock.leaveCriticalSection(); } + @Override + public boolean promote() { + if (!isInTransaction()) + throw new JenaTransactionException("Tried to promote outside a transaction!"); + if ( transactionMode().equals(ReadWrite.WRITE) ) + return true; + + boolean readCommitted; + // Initial state + switch(transactionType.get()) { + case WRITE : + return true; + case READ : + throw new JenaTransactionException("Tried to promote READ transaction"); + case READ_COMMITTED_PROMOTE : + readCommitted = true; + case READ_PROMOTE : + readCommitted = false; + // Maybe! + break; + default: + throw new NullPointerException(); + } + + try { + _promote(readCommitted); + return true; + } catch (JenaTransactionException ex) { + return false ; + } + } + + private void _promote(boolean readCommited) { + //System.err.printf("Promote: version=%d generation=%d\n", version.get() , generation.get()) ; + + // Outside lock. + if ( ! readCommited && version.get() != generation.get() ) { --- End diff -- Yes- that's what happens. This part of the code isn't new - only moved. The check is done twice, once before the lock, once again after to avoid unnecessary `transactionLock` taking. It's the same algorithm in TDB and TDB2. TDB and TDB2 have explicit `Transaction` objects that carry the start version. The shared tests cover all cases.
---