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 2017/02/28 22:52:58 UTC

[2/3] jena git commit: JENA-1296: Enter exclusive mode outside of synchronized(this) block

JENA-1296: Enter exclusive mode outside of synchronized(this) block

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

Branch: refs/heads/master
Commit: 75bd1e1314e717877df8b0747ae54eafffbc2c13
Parents: 2e34a14
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Feb 28 22:46:08 2017 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Feb 28 22:49:03 2017 +0000

----------------------------------------------------------------------
 .../tdb/transaction/TransactionManager.java     | 54 ++++++++++++++++----
 1 file changed, 44 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/75bd1e13/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 8d0bee9..63a5e35 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
@@ -307,7 +307,9 @@ public class TransactionManager
     public /*for testing only*/ static final boolean DEBUG = false ; 
     
     public DatasetGraphTxn begin(ReadWrite mode, String label) {
-        exclusivitylock.readLock().lock() ;
+        // The exclusivitylock surrounds the entire transaction cycle.
+        // Paired with notifyCommit, notifyAbort.
+        startNonExclusive();
         
         // Not synchronized (else blocking on semaphore will never wake up
         // because Semaphore.release is inside synchronized).
@@ -475,10 +477,9 @@ public class TransactionManager
 
     /* Signal a transaction has commited.  The journal has a commit record
      * and a sync to disk. The code here manages the inter-transaction stage
-     *  of deciding how to play the changes back to the base data
-     *  together with general recording of transaction details and status. 
+     * of deciding how to play the changes back to the base data
+     * together with general recording of transaction details and status. 
      */ 
-    synchronized
     /*package*/ void notifyCommit(Transaction transaction) {
         boolean excessiveQueue = false ;
         synchronized(this) {
@@ -496,12 +497,24 @@ public class TransactionManager
                     excessiveQueue = ( MaxQueueThreshold >= 0 && queue.size() > MaxQueueThreshold ) ;
                     releaseWriterLock();
             }
+            // Paired with begin()
+            finishNonExclusive();
         }
-        // Force the queue to flush because it is getting excessively long.
-        // Note that writers may happen between releaseWriterLock above and and startExclusiveMode.
+        // Force the queue to flush if it is getting excessively long.
+        // Note that writers may happen between releaseWriterLock above
+        // and exclusiveFlushQueue and so several writers may try to flush
+        // the queue; this is safe.        
+        
         if ( excessiveQueue ) {
-            startExclusiveMode(true) ;
-            finishExclusiveMode(); 
+            // Check again. This is an imperfect filter for multiple attempts to flush the queue
+            // and avoid going into exclusive mode.
+//            excessiveQueue = ( MaxQueueThreshold >= 0 && queue.size() > MaxQueueThreshold ) ;
+//            if ( excessiveQueue )
+                // Must have released the exclusivity lock (a read-MRSW lock) otherwise
+                // taking the exclusivity lock (a write-MRSW lock) in
+                // exclusiveFlushQueue->startExclusiveMode will block.
+                // Java MRSW locks do not allow "hold reader -> take writer".
+                exclusiveFlushQueue();
         }
     }
 
@@ -518,10 +531,13 @@ public class TransactionManager
             case READ: break ;
             case WRITE: releaseWriterLock();
         }
+        // Paired with begin()
+        finishNonExclusive();
     }
     
     synchronized
     /*package*/ void notifyClose(Transaction txn) {
+        // Caution - not called if "Transactional.end() is not called."
         if ( txn.getState() == TxnState.ACTIVE )
         {
             String x = txn.getBaseDataset().getLocation().getDirectoryPath() ;
@@ -588,6 +604,26 @@ public class TransactionManager
         releaseWriterLock();
     }
     
+    /** Force flushing the queue by entering exclusive mode.*/
+    private void exclusiveFlushQueue() {
+        startExclusiveMode(true) ;
+        finishExclusiveMode(); 
+    }
+
+    /** Start non-exclusive mode - this is the normal transaction mode.
+     * This does not relate to reader/writer. 
+     */
+    private void startNonExclusive() {
+        exclusivitylock.readLock().lock();
+    }
+    
+    /** Finish non-exclusive mode - this is the normal transaction mode.
+     * This does not relate to reader/writer. 
+     */
+    private void finishNonExclusive() {
+        exclusivitylock.readLock().unlock();
+    }
+
     /** Enter exclusive mode. 
      * <p>
      * There are no active transactions on return; new transactions will be held up in 'begin'.
@@ -797,7 +833,6 @@ public class TransactionManager
             case WRITE : writerCommits(transaction) ; break ;
         }
         transactionFinishes(transaction) ;
-        exclusivitylock.readLock().unlock() ;
     }
     
     private void noteTxnAbort(Transaction transaction) {
@@ -807,7 +842,6 @@ public class TransactionManager
             case WRITE : writerAborts(transaction) ; break ;
         }
         transactionFinishes(transaction) ;
-        exclusivitylock.readLock().unlock() ;
     }
     
     private void noteTxnClose(Transaction transaction) {