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/05/04 08:40:46 UTC

[5/9] jena git commit: JENA-1539: Txn nesting compatibility

JENA-1539: Txn nesting compatibility


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

Branch: refs/heads/master
Commit: dbce176ad7f9a422198c24f8b7b79cb3c1fe5d9f
Parents: 52377b8
Author: Andy Seaborne <an...@apache.org>
Authored: Sun Apr 29 17:22:31 2018 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Apr 29 17:22:31 2018 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/jena/system/Txn.java   | 45 ++++++++++-----
 .../java/org/apache/jena/system/TestTxn.java    | 61 ++++++++++++++++----
 .../apache/jena/system/TestTxnLifecycle.java    |  3 +-
 3 files changed, 83 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/dbce176a/jena-arq/src/main/java/org/apache/jena/system/Txn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/system/Txn.java b/jena-arq/src/main/java/org/apache/jena/system/Txn.java
index dc7158b..4ab2c82 100644
--- a/jena-arq/src/main/java/org/apache/jena/system/Txn.java
+++ b/jena-arq/src/main/java/org/apache/jena/system/Txn.java
@@ -18,6 +18,7 @@
 
 package org.apache.jena.system;
 
+import java.util.Objects;
 import java.util.function.Supplier ;
 
 import org.apache.jena.query.TxnType;
@@ -71,12 +72,9 @@ public class Txn {
     /** Execute application code in a transaction with the given {@link TxnType trasnaction type}. */
     public static <T extends Transactional> void exec(T txn, TxnType txnType, Runnable r) {
         boolean b = txn.isInTransaction() ;
-        if ( b )  {
-            TxnType txnTypeOuter = txn.transactionType();
-            if ( txnTypeOuter != txnType )
-                throw new JenaTransactionException("Already in a transaction of a different type: "
-                                                  +"outer="+txnTypeOuter+" : inner="+txnType);
-        } else
+        if (  b )
+            checkCompatible(txn, txnType);
+        else
             txn.begin(txnType) ;
         try { r.run() ; }
         catch (Throwable th) {
@@ -94,14 +92,10 @@ public class Txn {
     /** Execute and return a value in a transaction with the given {@link TxnType trasnaction type}. */
     public static <T extends Transactional, X> X calc(T txn, TxnType txnType, Supplier<X> r) {
         boolean b = txn.isInTransaction() ;
-        if ( b )  {
-            TxnType txnTypeOuter = txn.transactionType();
-            if ( txnTypeOuter != txnType )
-                throw new JenaTransactionException("Already in a transaction of a different type: "
-                                                  +"outer="+txnTypeOuter+" : inner="+txnType);
-        } else
+        if (  b )
+            checkCompatible(txn, txnType);
+        else
             txn.begin(txnType) ;
-    
         X x;
         try { x = r.get() ; } 
         catch (Throwable th) {
@@ -138,6 +132,31 @@ public class Txn {
         return calc(txn, TxnType.WRITE, r);
     }
     
+    /** Check the requested transaction {@code innerTxnType} is compatible with the transactional.
+     * @param txn
+     * @param innerTxnType
+     */
+    private static void checkCompatible(Transactional txn, TxnType innerTxnType) {
+        TxnType outerTxnType = txn.transactionType();
+        if ( outerTxnType == null ) 
+            // Not in an outer transaction.
+            return;
+        // innerTxnType must be "less than or equal to the outer.
+        // Inner is READ works with any outer.
+        // Outer is WRITE works with any inner. 
+        // Must match:
+        // Outer is READ, then inner must be READ.
+        // Promotion must be the same.
+        if ( TxnType.READ.equals(innerTxnType) )
+            return;
+        if ( TxnType.WRITE.equals(outerTxnType) )
+            return;
+        if ( Objects.equals(innerTxnType, outerTxnType) )
+            return;
+        throw new JenaTransactionException("Already in a transaction of an incompatable type: "
+                                          +"outer="+outerTxnType+" : inner="+innerTxnType);
+    }        
+    
     // Attempt some kind of cleanup.
     private static <T extends Transactional> void onThrowable(Throwable th, T txn) {
         try {

http://git-wip-us.apache.org/repos/asf/jena/blob/dbce176a/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java b/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
index 668efb5..901b9c6 100644
--- a/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestTxn.java
@@ -242,23 +242,36 @@ public class TestTxn {
         });
     }
 
-    @Test(expected=JenaTransactionException.class)
+    @Test
     public void txn_nested_02() {
-        Txn.exec(counter, TxnType.READ, ()->{
-            Txn.exec(counter, TxnType.WRITE, ()->{});
+        Txn.exec(counter, TxnType.WRITE, ()->{
+            Txn.exec(counter, TxnType.READ, ()->{});
         });
     }
 
-    @Test(expected=JenaTransactionException.class)
+    @Test
     public void txn_nested_03() {
-        Txn.exec(counter, TxnType.WRITE, ()->{
-            // Must the same type to nest Txn.
+        Txn.exec(counter, TxnType.READ_PROMOTE, ()->{
             Txn.exec(counter, TxnType.READ, ()->{});
         });
     }
 
     @Test
     public void txn_nested_04() {
+        Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{
+            Txn.exec(counter, TxnType.READ, ()->{});
+        });
+    }
+
+    @Test(expected=JenaTransactionException.class)
+    public void txn_nested_05() {
+        Txn.exec(counter, TxnType.READ, ()->{
+            Txn.exec(counter, TxnType.WRITE, ()->{});
+        });
+    }
+
+    @Test
+    public void txn_nested_06() {
         Txn.exec(counter, TxnType.READ_PROMOTE, ()->{
             boolean b = counter.promote();
             assertTrue(b);
@@ -268,23 +281,49 @@ public class TestTxn {
     }
 
     @Test
-    public void txn_nested_05() {
-        Txn.exec(counter, TxnType.READ_PROMOTE, ()->{
+    public void txn_nested_07() {
+        Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{
+            boolean b = counter.promote();
+            assertTrue(b);
+            // Must the same type to nest Txn.
+            Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{});
+        });
+    }
+
+    @Test
+    public void txn_nested_08() {
+        Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{
             boolean b = counter.promote();
             assertTrue(b);
             assertEquals(ReadWrite.WRITE, counter.transactionMode());
             // Must the same type to nest Txn.
-            Txn.exec(counter, TxnType.READ_PROMOTE, ()->{});
+            Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{});
         });
     }
 
-    @Test(expected=JenaTransactionException.class)
-    public void txn_nested_06() {
+    @Test
+    public void txn_nested_09() {
         Txn.exec(counter, TxnType.READ_PROMOTE, ()->{
             boolean b = counter.promote();
             assertTrue(b);
             assertEquals(ReadWrite.WRITE, counter.transactionMode());
             // Must the same type to nest Txn.
+            Txn.exec(counter, TxnType.READ_PROMOTE, ()->{});
+        });
+    }
+
+    @Test(expected=JenaTransactionException.class)
+    public void txn_nested_10() {
+        Txn.exec(counter, TxnType.READ_PROMOTE, ()->{
+            // Must the same type to nest Txn.
+            Txn.exec(counter, TxnType.WRITE, ()->{});
+        });
+    }
+
+    @Test(expected=JenaTransactionException.class)
+    public void txn_nested_11() {
+        Txn.exec(counter, TxnType.READ_COMMITTED_PROMOTE, ()->{
+            // Must the same type to nest Txn.
             Txn.exec(counter, TxnType.WRITE, ()->{});
         });
     }

http://git-wip-us.apache.org/repos/asf/jena/blob/dbce176a/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java b/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
index 76ae02e..bf65468 100644
--- a/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestTxnLifecycle.java
@@ -72,10 +72,9 @@ public class TestTxnLifecycle {
         assertEquals(56,x) ;
     }
     
-    @Test(expected=JenaTransactionException.class)
+    @Test
     public void txn_lifecycle_05b() {
         int x = Txn.calculateWrite(trans, ()-> {
-            // Does not continue outer transaction.
             return Txn.calculateRead(trans, ()->56) ;
         });
         assertEquals(56,x) ;