You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2018/01/30 11:18:41 UTC

[3/5] jena git commit: JENA-1469: Adjust internal tracking state across promotion

JENA-1469: Adjust internal tracking state across promotion


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/fb172399
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/fb172399
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/fb172399

Branch: refs/heads/master
Commit: fb172399ff2181a8f5f82e5988424defdf38da67
Parents: 3ac175b
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jan 27 17:11:22 2018 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jan 27 17:11:22 2018 +0000

----------------------------------------------------------------------
 .../transaction/AbstractTestTransPromote.java   | 26 ++++-----
 .../AbstractTestTransactionLifecycle.java       | 24 +++++++-
 .../tdb/transaction/TransactionManager.java     | 59 ++++++++++++--------
 3 files changed, 72 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/fb172399/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java
index 9134668..1ca1379 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransPromote.java
@@ -244,18 +244,6 @@ public abstract class AbstractTestTransPromote {
         }) ;
     }
 
-    @Test
-    public void promote_10() { promote_readCommit_txnCommit(TxnType.READ_COMMITTED_PROMOTE, true) ; }
-
-    @Test
-    public void promote_11() { promote_readCommit_txnCommit(TxnType.READ_COMMITTED_PROMOTE, false) ; }
-    
-    @Test
-    public void promote_12() { 
-        expect(()->promote_readCommit_txnCommit(TxnType.READ_PROMOTE, true) ,
-               getTransactionExceptionClass()) ;
-    }
-    
     @SafeVarargs
     private final void expect(Runnable runnable, Class<? extends Exception>...classes) {
         try {
@@ -271,6 +259,18 @@ public abstract class AbstractTestTransPromote {
     }
 
     @Test
+    public void promote_10() { promote_readCommit_txnCommit(TxnType.READ_COMMITTED_PROMOTE, true) ; }
+
+    @Test
+    public void promote_11() { promote_readCommit_txnCommit(TxnType.READ_COMMITTED_PROMOTE, false) ; }
+    
+    @Test
+    public void promote_12() { 
+        expect(()->promote_readCommit_txnCommit(TxnType.READ_PROMOTE, true) ,
+               getTransactionExceptionClass()) ;
+    }
+    
+    @Test
     public void promote_13() { promote_readCommit_txnCommit(TxnType.READ_PROMOTE, false) ; }
 
     private void promote_readCommit_txnCommit(TxnType txnType, boolean asyncCommit) {
@@ -388,7 +388,7 @@ public abstract class AbstractTestTransPromote {
         } catch (InterruptedException | ExecutionException e1) { throw new RuntimeException(e1) ; }
     }
     
-    // This would locks up because of a WRITE-WRITE deadly embrace.
+    // This would lock up because of a WRITE-WRITE deadly embrace.
     //  @Test(expected=JenaTransactionException.class)
     //  public void promote11() { test2(TxnMode.WRITE); }
       

http://git-wip-us.apache.org/repos/asf/jena/blob/fb172399/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
index c1043b8..ec80425 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/transaction/AbstractTestTransactionLifecycle.java
@@ -235,6 +235,17 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest
         ds.end();
     }
     
+    // JENA-1469
+    @Test
+    public void transaction_p06() {
+        transaction_promote_write(TxnType.READ_COMMITTED_PROMOTE);
+    }
+
+    @Test
+    public void transaction_p07() {
+        transaction_promote_write(TxnType.READ_PROMOTE);
+    }
+
     @Test(expected=JenaException.class)
     public void transaction_err_read_promote() {
         assumeTrue(supportsPromote()) ;
@@ -245,9 +256,18 @@ public abstract class AbstractTestTransactionLifecycle extends BaseTest
         ds.commit();
         ds.end();
     }
-    
-    // XXX READ_PROMOTE -> update -> fail promote/boolean. 
 
+    private void transaction_promote_write(TxnType txnType) {
+        Dataset ds = create() ;
+        ds.begin(txnType);
+        ds.promote();
+        ds.commit();
+        ds.end();
+        ds.begin(TxnType.WRITE);
+        ds.commit();
+        ds.end(); 
+    }
+    
     // Patterns.
     @Test
     public void transaction_pattern_01() {

http://git-wip-us.apache.org/repos/asf/jena/blob/fb172399/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java
----------------------------------------------------------------------
diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java
index 10e8b44..e9c4797 100644
--- a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java
+++ b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java
@@ -163,7 +163,7 @@ public class TransactionManager
         void transactionCloses(Transaction txn) ;
         void readerStarts(Transaction txn) ;
         void readerFinishes(Transaction txn) ;
-        void transactionPromotes(Transaction txn) ;
+        void transactionPromotes(Transaction txnOld, Transaction txnNew) ;
         void writerStarts(Transaction txn) ;
         void writerCommits(Transaction txn) ;
         void writerAborts(Transaction txn) ;
@@ -175,7 +175,7 @@ public class TransactionManager
         @Override public void transactionCloses(Transaction txn)    {}
         @Override public void readerStarts(Transaction txn)         {}
         @Override public void readerFinishes(Transaction txn)       {}
-        @Override public void transactionPromotes(Transaction txn)  {}
+        @Override public void transactionPromotes(Transaction txnOld, Transaction txnNew) {}
         @Override public void writerStarts(Transaction txn)         {}
         @Override public void writerCommits(Transaction txn)        {}
         @Override public void writerAborts(Transaction txn)         {}
@@ -185,7 +185,8 @@ public class TransactionManager
         TSM_Logger() {}
         @Override public void readerStarts(Transaction txn)         { log("start", txn) ; }
         @Override public void readerFinishes(Transaction txn)       { log("finish", txn) ; }
-        @Override public void transactionPromotes(Transaction txn)  { log("promote", txn) ; }
+        @Override public void transactionPromotes(Transaction txnOld, Transaction txnNew)
+        { log("promote(old)", txnOld) ; log("promote(new)", txnNew) ; }  
         @Override public void writerStarts(Transaction txn)         { log("begin", txn) ; }
         @Override public void writerCommits(Transaction txn)        { log("commit", txn) ; }
         @Override public void writerAborts(Transaction txn)         { log("abort", txn) ; }
@@ -196,7 +197,8 @@ public class TransactionManager
         TSM_LoggerDebug() {}
         @Override public void readerStarts(Transaction txn)         { logInternal("start",  txn) ; }
         @Override public void readerFinishes(Transaction txn)       { logInternal("finish", txn) ; }
-        @Override public void transactionPromotes(Transaction txn)  { logInternal("promote", txn) ; }
+        @Override public void transactionPromotes(Transaction txnOld, Transaction txnNew)
+        { logInternal("promote(old)", txnOld) ; logInternal("promote(new)", txnNew) ; }  
         @Override public void writerStarts(Transaction txn)         { logInternal("begin",  txn) ; }
         @Override public void writerCommits(Transaction txn)        { logInternal("commit", txn) ; }
         @Override public void writerAborts(Transaction txn)         { logInternal("abort",  txn) ; }
@@ -209,7 +211,10 @@ public class TransactionManager
         @Override public void transactionCloses(Transaction txn)    { }
         @Override public void readerStarts(Transaction txn)         { inc(activeReaders) ; }
         @Override public void readerFinishes(Transaction txn)       { dec(activeReaders) ; inc(finishedReaders); }
-        @Override public void transactionPromotes(Transaction txn)  { dec(activeReaders) ; inc(finishedReaders); inc(activeWriters); }
+        
+        @Override public void transactionPromotes(Transaction txnOld, Transaction txnNew)
+        { dec(activeReaders) ; inc(finishedReaders); inc(activeWriters); }
+        
         @Override public void writerStarts(Transaction txn)         { inc(activeWriters) ; }
         @Override public void writerCommits(Transaction txn)        { dec(activeWriters) ; inc(committedWriters) ; }
         @Override public void writerAborts(Transaction txn)         { dec(activeWriters) ; inc(abortedWriters) ; }
@@ -236,6 +241,12 @@ public class TransactionManager
         
         // Currently, the writer semaphore is managed explicitly in the main code.
         
+        @Override public void transactionPromotes(Transaction txnOld, Transaction txnNew) {
+            // Switch locks.
+            txnOld.getBaseDataset().getLock().leaveCriticalSection() ;
+            txnNew.getBaseDataset().getLock().enterCriticalSection(Lock.READ) ;
+        }
+        
         @Override
         public void readerFinishes(Transaction txn) {
             txn.getBaseDataset().getLock().leaveCriticalSection() ;
@@ -342,7 +353,9 @@ public class TransactionManager
             acquireWriterLock(true) ;
         }
         // entry synchronized part
-        return begin$(txnType, originalTxnType, label) ;
+        DatasetGraphTxn dsgtxn = begin$(txnType, originalTxnType, label) ;
+        noteTxnStart(dsgtxn.getTransaction()) ;
+        return dsgtxn;
     }
     
     /** Ensure a DatasetGraphTxn is for a write transaction.
@@ -377,11 +390,9 @@ public class TransactionManager
         // Can also promote - may need to wait for active writers. 
         // Go through begin for the writers lock. 
         if ( txnType == TxnType.READ_COMMITTED_PROMOTE ) {
-            // Full begin cycle.
-            DatasetGraphTxn dsgtxn2 = beginInternal(TxnType.WRITE, txnType, txn.getLabel()) ;
-            // Junk the old one.
-            noteTxnPromote(txn, dsgtxn2.getTransaction());
-            return dsgtxn2 ;
+            acquireWriterLock(true);
+            // No need to sync - we just queue as a writer.
+            return promoteExec$(dsgtxn, txnType);
         }
         
         // First check, without the writer lock. Fast fail.
@@ -402,25 +413,31 @@ public class TransactionManager
         // Potentially blocking - must be outside 'synchronized' so that any active writer
         // can commit/abort.  Otherwise, we have deadlock.
         acquireWriterLock(true) ;
-
         // Do the synchronized stuff.
-        return promote2$(dsgtxn, txnType) ; 
+        return promoteSync$(dsgtxn, txnType) ; 
     }
     
     synchronized
-    private DatasetGraphTxn promote2$(DatasetGraphTxn dsgtxn, TxnType originalTxnType) {
+    private DatasetGraphTxn promoteSync$(DatasetGraphTxn dsgtxn, TxnType originalTxnType) {
         Transaction txn = dsgtxn.getTransaction() ;
         // Writers may have happened between the first check of the active writers may have committed.  
         if ( txn.getVersion() != version.get() ) {
             releaseWriterLock();
             return null;
         }
-        // Use begin$ (not beginInternal) - we have the writers lock.
+        return promoteExec$(dsgtxn, originalTxnType);
+    }
+    
+    private DatasetGraphTxn promoteExec$(DatasetGraphTxn dsgtxn, TxnType originalTxnType) {
+        // Use begin$ (not beginInternal)
+        // We have the writers lock.
+        // We keep the exclusivity lock.
+        Transaction txn = dsgtxn.getTransaction() ;
         DatasetGraphTxn dsgtxn2 = begin$(TxnType.WRITE, originalTxnType, txn.getLabel()) ;
         noteTxnPromote(txn, dsgtxn2.getTransaction());
         return dsgtxn2 ;
     }
-
+    
     // If DatasetGraphTransaction has a sync lock on sConn, this
     // does not need to be sync'ed. But it's possible to use some
     // of the low level objects directly so we'll play safe.  
@@ -450,6 +467,7 @@ public class TransactionManager
         txn.setActiveDataset(dsgTxn) ;
 
         // Empty for READ ; only WRITE transactions have components that need notifying.
+        // Promote is a WRITE transaction starting.
         List<TransactionLifecycle> components = dsgTxn.getTransaction().lifecycleComponents() ;
         
         if ( mode == ReadWrite.READ ) {
@@ -460,8 +478,6 @@ public class TransactionManager
         
         for ( TransactionLifecycle component : components )
             component.begin(dsgTxn.getTransaction()) ;
-
-        noteTxnStart(txn) ;
         return dsgTxn ;
     }
     
@@ -870,10 +886,9 @@ public class TransactionManager
     private void noteTxnPromote(Transaction transaction, Transaction transaction2) {
         activeTransactions.remove(transaction);
         activeTransactions.add(transaction2);
-        transactionPromotes(transaction) ;
+        transactionPromotes(transaction, transaction2) ;
     }
 
-
     private void noteTxnCommit(Transaction transaction) {
         switch (transaction.getTxnMode())
         {
@@ -1011,10 +1026,10 @@ public class TransactionManager
                 tsm.readerFinishes(txn) ;
     }
     
-    private void transactionPromotes(Transaction txn) {
+    private void transactionPromotes(Transaction txnOld, Transaction txnNew) {
         for ( TSM tsm : actions )
             if ( tsm != null )
-                tsm.transactionPromotes(txn);
+                tsm.transactionPromotes(txnOld, txnNew);
     }
 
     private void writerStarts(Transaction txn) {