1 //
2 // ResourceManager representing an integer, used by other test cases
3 //
4 // Author:
5 //	Ankit Jain	<JAnkit@novell.com>
6 //
7 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
8 //
9 
10 using System;
11 using System.Collections.Generic;
12 using System.Text;
13 using System.Transactions;
14 using NUnit.Framework;
15 
16 namespace MonoTests.System.Transactions
17 {
18     public class IntResourceManager
19     {
IntResourceManager(int value)20         public IntResourceManager (int value)
21         {
22             actual = value;
23             guid = Guid.NewGuid ();
24         }
25 
26         private int actual;
27         private int tmpValue;
28         private Transaction transaction = null;
29 
30         public int NumPrepare = 0;
31         public int NumRollback = 0;
32         public int NumCommit = 0;
33         public int NumInDoubt = 0;
34         public int NumSingle = 0;
35 
36         public int NumInitialize = 0;
37         public int NumPromote = 0;
38         public int NumEnlistFailed = 0;
39 
40         public ResourceManagerType Type = ResourceManagerType.Volatile;
41         public bool FailPrepare = false;
42         public bool FailWithException = false;
43         public bool IgnorePrepare = false;
44         public bool IgnoreSPC = false;
45         public bool FailSPC = false;
46         public bool FailCommit = false;
47 		public bool FailRollback = false;
48         public bool UseSingle = false;
49 		public Exception ThrowThisException = null;
50 
51         Guid guid;
52 
53         public int Actual {
54             get { return actual; }
55         }
56 
57         public int Value {
58             get { return transaction == null ? actual : tmpValue; }
59             set
60             {
61                 if (Transaction.Current == null) {
62                     /* Not in a transaction */
63                     actual = value;
64                     return;
65                 }
66                 /* FIXME: Do what in this case? */
67                 if (transaction != null)
68                     Console.WriteLine ("WARNING: Setting value more than once");
69 
70                 if (transaction != Transaction.Current) {
71                     transaction = Transaction.Current;
72 
73                     if ( Type == ResourceManagerType.Promotable ) {
74                         transaction.EnlistPromotableSinglePhase(new PromotableSinglePhaseNotification ( this ));
75                     } else if (UseSingle) {
76                         SinglePhaseNotification enlistment = new SinglePhaseNotification ( this );
77                         if ( Type == ResourceManagerType.Volatile )
78                             transaction.EnlistVolatile ( enlistment, EnlistmentOptions.None );
79                         else
80                             transaction.EnlistDurable ( guid, enlistment, EnlistmentOptions.None );
81                     } else {
82                         EnlistmentNotification enlistment = new EnlistmentNotification ( this );
83                         if ( Type == ResourceManagerType.Volatile )
84                             transaction.EnlistVolatile ( enlistment, EnlistmentOptions.None );
85                         else
86                             transaction.EnlistDurable ( guid, enlistment, EnlistmentOptions.None );
87                     }
88                 }
89                 tmpValue = value;
90             }
91         }
92 
Commit()93         public void Commit ()
94         {
95             actual = tmpValue;
96             transaction = null;
97         }
98 
Rollback()99         public void Rollback ()
100         {
101             transaction = null;
102         }
103 
CheckSPC( string msg )104         public  void CheckSPC ( string msg )
105         {
106             Check ( 1, 0, 0, 0, 0, 0, 0, msg );
107         }
108 
Check2PC( string msg)109         public void Check2PC ( string msg)
110         {
111             Check ( 0, 1, 1, 0, 0, 0, 0, msg );
112         }
113 
Check( int s, int p, int c, int r, int d, int i, int pr, string msg )114         public void Check ( int s, int p, int c, int r, int d, int i, int pr, string msg )
115         {
116             Assert.AreEqual ( s, NumSingle, msg + ": NumSingle" );
117             Assert.AreEqual ( p, NumPrepare, msg + ": NumPrepare" );
118             Assert.AreEqual ( c, NumCommit, msg + ": NumCommit" );
119             Assert.AreEqual ( r, NumRollback, msg + ": NumRollback" );
120             Assert.AreEqual ( d, NumInDoubt, msg + ": NumInDoubt" );
121             Assert.AreEqual ( i, NumInitialize, msg + ": NumInitialize" );
122             Assert.AreEqual ( pr, NumPromote, msg + ": NumPromote" );
123         }
124 
125         /* Used for volatile RMs */
Check( int p, int c, int r, int d, string msg )126         public void Check ( int p, int c, int r, int d, string msg )
127         {
128             Check ( 0, p, c, r, d, 0, 0, msg );
129         }
130     }
131 
132     public class EnlistmentNotification : IEnlistmentNotification {
133         protected IntResourceManager resource;
134 
EnlistmentNotification( IntResourceManager resource )135         public EnlistmentNotification ( IntResourceManager resource )
136         {
137             this.resource = resource;
138         }
139 
Prepare( PreparingEnlistment preparingEnlistment )140         public void Prepare ( PreparingEnlistment preparingEnlistment )
141         {
142             resource.NumPrepare++;
143             if ( resource.IgnorePrepare )
144                 return;
145 
146             if ( resource.FailPrepare ) {
147                 if (resource.FailWithException)
148                     preparingEnlistment.ForceRollback ( resource.ThrowThisException ?? new NotSupportedException () );
149                 else
150                     preparingEnlistment.ForceRollback ();
151             } else {
152                 preparingEnlistment.Prepared ();
153             }
154         }
155 
Commit( Enlistment enlistment )156         public void Commit ( Enlistment enlistment )
157         {
158             resource.NumCommit++;
159 			if (resource.FailCommit)
160 			{
161 				if (resource.FailWithException)
162 					throw (resource.ThrowThisException ?? new NotSupportedException());
163 				else
164 					return;
165 			}
166 
167             resource.Commit ();
168             enlistment.Done ();
169         }
170 
Rollback( Enlistment enlistment )171         public void Rollback ( Enlistment enlistment )
172         {
173             resource.NumRollback++;
174 			if (resource.FailRollback)
175 			{
176 				if (resource.FailWithException)
177 					throw (resource.ThrowThisException ?? new NotSupportedException());
178 				else
179 					return;
180 			}
181 
182             resource.Rollback ();
183         }
184 
InDoubt( Enlistment enlistment )185         public void InDoubt ( Enlistment enlistment )
186         {
187             resource.NumInDoubt++;
188             throw new Exception ( "IntResourceManager.InDoubt is not implemented." );
189         }
190     }
191 
192     public class SinglePhaseNotification : EnlistmentNotification, ISinglePhaseNotification
193     {
SinglePhaseNotification( IntResourceManager resource )194         public SinglePhaseNotification ( IntResourceManager resource )
195             : base ( resource )
196         {
197         }
198 
SinglePhaseCommit( SinglePhaseEnlistment enlistment )199         public void SinglePhaseCommit ( SinglePhaseEnlistment enlistment )
200         {
201             resource.NumSingle++;
202             if ( resource.IgnoreSPC )
203                 return;
204 
205             if ( resource.FailSPC ) {
206                 if ( resource.FailWithException )
207                     enlistment.Aborted ( resource.ThrowThisException ?? new NotSupportedException () );
208                 else
209                     enlistment.Aborted ();
210             }
211             else {
212                 resource.Commit ();
213                 enlistment.Committed ();
214             }
215         }
216     }
217 
218     public class PromotableSinglePhaseNotification : SinglePhaseNotification, IPromotableSinglePhaseNotification
219     {
PromotableSinglePhaseNotification( IntResourceManager resource )220         public PromotableSinglePhaseNotification ( IntResourceManager resource )
221             : base( resource )
222         {
223         }
224 
Initialize()225         public void Initialize ()
226         {
227             resource.NumInitialize++;
228         }
229 
Rollback( SinglePhaseEnlistment enlistment )230         public void Rollback ( SinglePhaseEnlistment enlistment )
231         {
232             resource.NumRollback++;
233             resource.Rollback ();
234         }
235 
Promote()236         public byte [] Promote ()
237         {
238             resource.NumPromote++;
239             return new byte[0];
240         }
241     }
242 
243     public enum ResourceManagerType { Volatile, Durable, Promotable };
244 }
245 
246