1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Diagnostics;
6 using System.Threading;
7 
8 namespace System.Transactions
9 {
10     // Base class for all enlistment states
11     internal abstract class EnlistmentState
12     {
EnterState(InternalEnlistment enlistment)13         internal abstract void EnterState(InternalEnlistment enlistment);
14 
15         internal static EnlistmentStatePromoted _enlistmentStatePromoted;
16 
17         // Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) )
18         private static object s_classSyncObject;
19 
20         internal static EnlistmentStatePromoted EnlistmentStatePromoted =>
21             LazyInitializer.EnsureInitialized(ref _enlistmentStatePromoted, ref s_classSyncObject, () => new EnlistmentStatePromoted());
22 
EnlistmentDone(InternalEnlistment enlistment)23         internal virtual void EnlistmentDone(InternalEnlistment enlistment)
24         {
25             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
26         }
27 
Prepared(InternalEnlistment enlistment)28         internal virtual void Prepared(InternalEnlistment enlistment)
29         {
30             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
31         }
32 
ForceRollback(InternalEnlistment enlistment, Exception e)33         internal virtual void ForceRollback(InternalEnlistment enlistment, Exception e)
34         {
35             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
36         }
37 
Committed(InternalEnlistment enlistment)38         internal virtual void Committed(InternalEnlistment enlistment)
39         {
40             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
41         }
42 
Aborted(InternalEnlistment enlistment, Exception e)43         internal virtual void Aborted(InternalEnlistment enlistment, Exception e)
44         {
45             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
46         }
47 
InDoubt(InternalEnlistment enlistment, Exception e)48         internal virtual void InDoubt(InternalEnlistment enlistment, Exception e)
49         {
50             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
51         }
52 
RecoveryInformation(InternalEnlistment enlistment)53         internal virtual byte[] RecoveryInformation(InternalEnlistment enlistment)
54         {
55             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
56         }
57 
InternalAborted(InternalEnlistment enlistment)58         internal virtual void InternalAborted(InternalEnlistment enlistment)
59         {
60             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
61             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
62         }
63 
InternalCommitted(InternalEnlistment enlistment)64         internal virtual void InternalCommitted(InternalEnlistment enlistment)
65         {
66             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
67             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
68         }
69 
InternalIndoubt(InternalEnlistment enlistment)70         internal virtual void InternalIndoubt(InternalEnlistment enlistment)
71         {
72             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
73             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
74         }
75 
ChangeStateCommitting(InternalEnlistment enlistment)76         internal virtual void ChangeStateCommitting(InternalEnlistment enlistment)
77         {
78             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
79             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
80         }
81 
ChangeStatePromoted(InternalEnlistment enlistment, IPromotedEnlistment promotedEnlistment)82         internal virtual void ChangeStatePromoted(InternalEnlistment enlistment, IPromotedEnlistment promotedEnlistment)
83         {
84             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
85             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
86         }
87 
ChangeStateDelegated(InternalEnlistment enlistment)88         internal virtual void ChangeStateDelegated(InternalEnlistment enlistment)
89         {
90             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
91             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
92         }
93 
ChangeStatePreparing(InternalEnlistment enlistment)94         internal virtual void ChangeStatePreparing(InternalEnlistment enlistment)
95         {
96             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
97             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
98         }
99 
ChangeStateSinglePhaseCommit(InternalEnlistment enlistment)100         internal virtual void ChangeStateSinglePhaseCommit(InternalEnlistment enlistment)
101         {
102             Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType()));
103             throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
104         }
105     }
106 
107     internal class EnlistmentStatePromoted : EnlistmentState
108     {
EnterState(InternalEnlistment enlistment)109         internal override void EnterState(InternalEnlistment enlistment)
110         {
111             enlistment.State = this;
112         }
113 
EnlistmentDone(InternalEnlistment enlistment)114         internal override void EnlistmentDone(InternalEnlistment enlistment)
115         {
116             Monitor.Exit(enlistment.SyncRoot);
117             try
118             {
119                 enlistment.PromotedEnlistment.EnlistmentDone();
120             }
121             finally
122             {
123                 Monitor.Enter(enlistment.SyncRoot);
124             }
125         }
126 
Prepared(InternalEnlistment enlistment)127         internal override void Prepared(InternalEnlistment enlistment)
128         {
129             Monitor.Exit(enlistment.SyncRoot);
130             try
131             {
132                 enlistment.PromotedEnlistment.Prepared();
133             }
134             finally
135             {
136                 Monitor.Enter(enlistment.SyncRoot);
137             }
138         }
139 
ForceRollback(InternalEnlistment enlistment, Exception e)140         internal override void ForceRollback(InternalEnlistment enlistment, Exception e)
141         {
142             Monitor.Exit(enlistment.SyncRoot);
143             try
144             {
145                 enlistment.PromotedEnlistment.ForceRollback(e);
146             }
147             finally
148             {
149                 Monitor.Enter(enlistment.SyncRoot);
150             }
151         }
152 
Committed(InternalEnlistment enlistment)153         internal override void Committed(InternalEnlistment enlistment)
154         {
155             Monitor.Exit(enlistment.SyncRoot);
156             try
157             {
158                 enlistment.PromotedEnlistment.Committed();
159             }
160             finally
161             {
162                 Monitor.Enter(enlistment.SyncRoot);
163             }
164         }
165 
Aborted(InternalEnlistment enlistment, Exception e)166         internal override void Aborted(InternalEnlistment enlistment, Exception e)
167         {
168             Monitor.Exit(enlistment.SyncRoot);
169             try
170             {
171                 enlistment.PromotedEnlistment.Aborted(e);
172             }
173             finally
174             {
175                 Monitor.Enter(enlistment.SyncRoot);
176             }
177         }
178 
InDoubt(InternalEnlistment enlistment, Exception e)179         internal override void InDoubt(InternalEnlistment enlistment, Exception e)
180         {
181             Monitor.Exit(enlistment.SyncRoot);
182             try
183             {
184                 enlistment.PromotedEnlistment.InDoubt(e);
185             }
186             finally
187             {
188                 Monitor.Enter(enlistment.SyncRoot);
189             }
190         }
191 
RecoveryInformation(InternalEnlistment enlistment)192         internal override byte[] RecoveryInformation(InternalEnlistment enlistment)
193         {
194             Monitor.Exit(enlistment.SyncRoot);
195             try
196             {
197                 return enlistment.PromotedEnlistment.GetRecoveryInformation();
198             }
199             finally
200             {
201                 Monitor.Enter(enlistment.SyncRoot);
202             }
203         }
204     }
205 }
206