Github user ajs6f commented on a diff in the pull request:

    https://github.com/apache/jena/pull/336#discussion_r159729634
  
    --- 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 --
    
    Just checking that I understand the algo here...
    
    1. Every transaction pulls a version number from the current generation 
number.
    2. A commit increments the generation number.
    3. When a transaction attempts to promote, it checks to see that the 
generation hasn't incremented out from under it (indicating that some other 
transaction committed since this one began). If that happened, this transaction 
will throw an exception as shown below.
    4. Otherwise, it's okay to promote.
    
    So two questions:
    1. Is that understanding accurate?
    2. Is that essentially how this is implemented in other dataset impls, or 
do I need to go read them as well?


---

Reply via email to