Merge pull request #3071 from adamburgess/fix-ci-links
[mono.git] / mcs / class / System.Transactions / System.Transactions / TransactionScope.cs
index d996b785700bbfb88f2cc27eabb0c5faf8b22d84..167d47e8d3a70e0a84be852e860f0e84c2bd10d0 100644 (file)
@@ -9,7 +9,6 @@
 // (C)2006 Novell Inc,
 //
 
-#if NET_2_0
 
 using DTCOption = System.Transactions.EnterpriseServicesInteropOption;
 
@@ -32,12 +31,20 @@ namespace System.Transactions
                bool completed;
                bool isRoot;
 
+               bool asyncFlowEnabled;
+
                public TransactionScope ()
                        : this (TransactionScopeOption.Required,
                                TransactionManager.DefaultTimeout)
                {
                }
 
+               public TransactionScope(TransactionScopeAsyncFlowOption asyncFlow)
+                       : this(TransactionScopeOption.Required,
+                               TransactionManager.DefaultTimeout, asyncFlow)
+               {
+               }
+
                public TransactionScope (Transaction transaction)
                        : this (transaction, TransactionManager.DefaultTimeout)
                {
@@ -54,7 +61,7 @@ namespace System.Transactions
                        TimeSpan timeout, DTCOption opt)
                {
                        Initialize (TransactionScopeOption.Required,
-                               transaction, defaultOptions, opt, timeout);
+                               transaction, defaultOptions, opt, timeout, TransactionScopeAsyncFlowOption.Suppress);
                }
 
                public TransactionScope (TransactionScopeOption option)
@@ -63,10 +70,21 @@ namespace System.Transactions
                }
 
                public TransactionScope (TransactionScopeOption option,
-                       TimeSpan timeout)
+                       TimeSpan timeout)
+                       : this (option, timeout, TransactionScopeAsyncFlowOption.Suppress)
+               {
+               }
+
+               public TransactionScope(TransactionScopeOption option, TransactionScopeAsyncFlowOption asyncFlow)
+                       : this(option, TransactionManager.DefaultTimeout, asyncFlow)
+               {
+               }
+
+       public TransactionScope (TransactionScopeOption option,
+                       TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow)
                {
                        Initialize (option, null, defaultOptions,
-                               DTCOption.None, timeout);
+                               DTCOption.None, timeout, asyncFlow);
                }
 
                public TransactionScope (TransactionScopeOption scopeOption,
@@ -81,16 +99,17 @@ namespace System.Transactions
                        DTCOption opt)
                {
                        Initialize (scopeOption, null, options, opt,
-                               TransactionManager.DefaultTimeout);
+                               TransactionManager.DefaultTimeout, TransactionScopeAsyncFlowOption.Suppress);
                }
 
                void Initialize (TransactionScopeOption scopeOption,
                        Transaction tx, TransactionOptions options,
-                       DTCOption interop, TimeSpan timeout)
+                       DTCOption interop, TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow)
                {
                        completed = false;
                        isRoot = false;
                        nested = 0;
+                       asyncFlowEnabled = asyncFlow == TransactionScopeAsyncFlowOption.Enabled;
 
                        if (timeout < TimeSpan.Zero)
                                throw new ArgumentOutOfRangeException ("timeout");
@@ -166,40 +185,70 @@ namespace System.Transactions
                                throw new InvalidOperationException ("TransactionScope nested incorrectly");
                        }
 
-                       if (Transaction.CurrentInternal != transaction) {
+                       if (Transaction.CurrentInternal != transaction && !asyncFlowEnabled) {
                                if (transaction != null)
                                        transaction.Rollback ();
                                if (Transaction.CurrentInternal != null)
                                        Transaction.CurrentInternal.Rollback ();
 
                                throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
-                       }
+                       } 
 
-                       if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
-                               oldTransaction.Scope = parentScope;
+                       if (asyncFlowEnabled) {
+                               if (oldTransaction != null)
+                                       oldTransaction.Scope = parentScope;
 
-                       Transaction.CurrentInternal = oldTransaction;
+                               var variedTransaction = Transaction.CurrentInternal;
 
-                       if (transaction == null)
-                               /* scope was not in a transaction, (Suppress) */
-                               return;
+                               if (transaction == null && variedTransaction == null)
+                                       /* scope was not in a transaction, (Suppress) */
+                                       return;
 
-                       transaction.Scope = null;
+                               variedTransaction.Scope = parentScope;
+                               Transaction.CurrentInternal = oldTransaction;
 
-                       if (!IsComplete) {
-                               transaction.Rollback ();
-                               return;
-                       }
+                               transaction.Scope = null;
 
-                       if (!isRoot)
-                               /* Non-root scope has completed+ended */
-                               return;
+                               if (!IsComplete) {
+                                       transaction.Rollback ();
+                                       variedTransaction.Rollback();
+                                       return;
+                               }
+
+                               if (!isRoot)
+                                       /* Non-root scope has completed+ended */
+                                       return;
+
+                               variedTransaction.CommitInternal();
+                               transaction.CommitInternal();
+                       } else {
+                               if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
+                                       oldTransaction.Scope = parentScope;
+
+                               Transaction.CurrentInternal = oldTransaction;
 
-                       transaction.CommitInternal ();
+                               if (transaction == null)
+                                       /* scope was not in a transaction, (Suppress) */
+                                       return;
+
+                               transaction.Scope = null;
+
+                               if (!IsComplete)
+                               {
+                                       transaction.Rollback();
+                                       return;
+                               }
+
+                               if (!isRoot)
+                                       /* Non-root scope has completed+ended */
+                                       return;
+
+                               transaction.CommitInternal();
+
+                       }
                }
 
 
        }
 }
 
-#endif