[System.Net] Add support for .pac proxy config scripts on mac
[mono.git] / mcs / class / System.Transactions / System.Transactions / TransactionScope.cs
1 //
2 // TransactionScope.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //      Ankit Jain       <JAnkit@novell.com>
7 //
8 // (C)2005 Novell Inc,
9 // (C)2006 Novell Inc,
10 //
11
12 #if NET_2_0
13
14 using DTCOption = System.Transactions.EnterpriseServicesInteropOption;
15
16 namespace System.Transactions
17 {
18         public sealed class TransactionScope : IDisposable
19         {
20                 static TransactionOptions defaultOptions =
21                         new TransactionOptions (0, TransactionManager.DefaultTimeout);
22
23                 Transaction transaction;
24                 Transaction oldTransaction;
25                 TransactionScope parentScope;
26                 TimeSpan timeout;
27
28                 /* Num of non-disposed nested scopes */
29                 int nested;
30
31                 bool disposed;
32                 bool completed;
33                 bool isRoot;
34
35                 public TransactionScope ()
36                         : this (TransactionScopeOption.Required,
37                                 TransactionManager.DefaultTimeout)
38                 {
39                 }
40
41                 public TransactionScope (Transaction transaction)
42                         : this (transaction, TransactionManager.DefaultTimeout)
43                 {
44                 }
45
46                 public TransactionScope (Transaction transaction,
47                         TimeSpan timeout)
48                         : this (transaction, timeout, DTCOption.None)
49                 {
50                 }
51
52                 [MonoTODO ("EnterpriseServicesInteropOption not supported.")]
53                 public TransactionScope (Transaction transaction,
54                         TimeSpan timeout, DTCOption opt)
55                 {
56                         Initialize (TransactionScopeOption.Required,
57                                 transaction, defaultOptions, opt, timeout);
58                 }
59
60                 public TransactionScope (TransactionScopeOption option)
61                         : this (option, TransactionManager.DefaultTimeout)
62                 {
63                 }
64
65                 [MonoTODO ("No TimeoutException is thrown")]
66                 public TransactionScope (TransactionScopeOption option,
67                         TimeSpan timeout)
68                 {
69                         Initialize (option, null, defaultOptions,
70                                 DTCOption.None, timeout);
71                 }
72
73                 public TransactionScope (TransactionScopeOption scopeOption,
74                         TransactionOptions options)
75                         : this (scopeOption, options, DTCOption.None)
76                 {
77                 }
78
79                 [MonoTODO ("EnterpriseServicesInteropOption not supported")]
80                 public TransactionScope (TransactionScopeOption scopeOption,
81                         TransactionOptions options,
82                         DTCOption opt)
83                 {
84                         Initialize (scopeOption, null, options, opt,
85                                 TransactionManager.DefaultTimeout);
86                 }
87
88                 void Initialize (TransactionScopeOption scopeOption,
89                         Transaction tx, TransactionOptions options,
90                         DTCOption interop, TimeSpan timeout)
91                 {
92                         completed = false;
93                         isRoot = false;
94                         nested = 0;
95                         this.timeout = timeout;
96
97                         oldTransaction = Transaction.CurrentInternal;
98
99                         Transaction.CurrentInternal = transaction = InitTransaction (tx, scopeOption);
100                         if (transaction != null)
101                                 transaction.InitScope (this);
102                         if (parentScope != null)
103                                 parentScope.nested ++;
104                 }
105
106                 Transaction InitTransaction (Transaction tx, TransactionScopeOption scopeOption)
107                 {
108                         if (tx != null)
109                                 return tx;
110                                 
111                         if (scopeOption == TransactionScopeOption.Suppress) {
112                                 if (Transaction.CurrentInternal != null)
113                                         parentScope = Transaction.CurrentInternal.Scope;
114                                 return null;
115                         }
116
117                         if (scopeOption == TransactionScopeOption.Required) {
118                                 if (Transaction.CurrentInternal == null) {
119                                         isRoot = true;
120                                         return new Transaction ();
121                                 }
122
123                                 parentScope = Transaction.CurrentInternal.Scope;
124                                 return Transaction.CurrentInternal;
125                         }
126
127                         /* RequiresNew */
128                         if (Transaction.CurrentInternal != null)
129                                 parentScope = Transaction.CurrentInternal.Scope;
130                         isRoot = true;
131                         return new Transaction ();
132                 }
133
134                 public void Complete ()
135                 {
136                         if (completed)
137                                 throw new InvalidOperationException ("The current TransactionScope is already complete. You should dispose the TransactionScope.");
138
139                         completed = true;
140                 }
141
142                 internal bool IsComplete {
143                         get { return completed; }
144                 }
145
146                 internal TimeSpan Timeout
147                 {
148                         get { return timeout; }
149                 }
150
151                 public void Dispose ()
152                 {
153                         if (disposed)
154                                 return;
155
156                         disposed = true;
157
158                         if (parentScope != null)
159                                 parentScope.nested --;
160
161                         if (nested > 0) {
162                                 transaction.Rollback ();
163                                 throw new InvalidOperationException ("TransactionScope nested incorrectly");
164                         }
165
166                         if (Transaction.CurrentInternal != transaction) {
167                                 if (transaction != null)
168                                         transaction.Rollback ();
169                                 if (Transaction.CurrentInternal != null)
170                                         Transaction.CurrentInternal.Rollback ();
171
172                                 throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
173                         }
174
175                         if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
176                                 oldTransaction.Scope = parentScope;
177
178                         Transaction.CurrentInternal = oldTransaction;
179
180                         if (transaction == null)
181                                 /* scope was not in a transaction, (Suppress) */
182                                 return;
183
184                         transaction.Scope = null;
185
186                         if (!IsComplete) {
187                                 transaction.Rollback ();
188                                 return;
189                         }
190
191                         if (!isRoot)
192                                 /* Non-root scope has completed+ended */
193                                 return;
194
195                         transaction.CommitInternal ();
196                 }
197
198
199         }
200 }
201
202 #endif