disable broken tests on net_4_0
[mcs.git] / class / Npgsql / Npgsql / NpgsqlPromotableSinglePhaseNotification.cs
blobb029597fb2c60acf363d306b7a75a1a5780c1e2f
1 // NpgsqlPromotableSinglePhaseNotification.cs
2 //
3 // Author:
4 // Josh Cooley <jbnpgsql@tuxinthebox.net>
5 //
6 // Copyright (C) 2007, The Npgsql Development Team
7 //
8 // Permission to use, copy, modify, and distribute this software and its
9 // documentation for any purpose, without fee, and without a written
10 // agreement is hereby granted, provided that the above copyright notice
11 // and this paragraph and the following two paragraphs appear in all copies.
12 //
13 // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
14 // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
15 // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
16 // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
17 // THE POSSIBILITY OF SUCH DAMAGE.
18 //
19 // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
20 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
23 // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 using System;
26 using System.Transactions;
28 namespace Npgsql
30 internal class NpgsqlPromotableSinglePhaseNotification : IPromotableSinglePhaseNotification
32 private readonly NpgsqlConnection _connection;
33 private IsolationLevel _isolationLevel;
34 private NpgsqlTransaction _npgsqlTx;
35 private NpgsqlTransactionCallbacks _callbacks;
36 private INpgsqlResourceManager _rm;
37 private bool _inTransaction;
39 private static readonly String CLASSNAME = "NpgsqlPromotableSinglePhaseNotification";
41 public NpgsqlPromotableSinglePhaseNotification(NpgsqlConnection connection)
43 _connection = connection;
46 public void Enlist(Transaction tx)
48 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Enlist");
49 if (tx != null)
51 _isolationLevel = tx.IsolationLevel;
52 if (!tx.EnlistPromotableSinglePhase(this))
54 // must already have a durable resource
55 // start transaction
56 _npgsqlTx = _connection.BeginTransaction(ConvertIsolationLevel(_isolationLevel));
57 _inTransaction = true;
58 _rm = CreateResourceManager();
59 _callbacks = new NpgsqlTransactionCallbacks(_connection);
60 _rm.Enlist(_callbacks, TransactionInterop.GetTransmitterPropagationToken(tx));
61 // enlisted in distributed transaction
62 // disconnect and cleanup local transaction
63 _npgsqlTx.Cancel();
64 _npgsqlTx.Dispose();
65 _npgsqlTx = null;
70 /// <summary>
71 /// Used when a connection is closed
72 /// </summary>
73 public void Prepare()
75 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Prepare");
76 if (_inTransaction)
78 // may not be null if Promote or Enlist is called first
79 if (_callbacks == null)
81 _callbacks = new NpgsqlTransactionCallbacks(_connection);
83 _callbacks.PrepareTransaction();
84 if (_npgsqlTx != null)
86 // cancel the NpgsqlTransaction since this will
87 // be handled by a two phase commit.
88 _npgsqlTx.Cancel();
89 _npgsqlTx.Dispose();
90 _npgsqlTx = null;
95 #region IPromotableSinglePhaseNotification Members
97 public void Initialize()
99 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Initialize");
100 _npgsqlTx = _connection.BeginTransaction(ConvertIsolationLevel(_isolationLevel));
101 _inTransaction = true;
104 public void Rollback(SinglePhaseEnlistment singlePhaseEnlistment)
106 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Rollback");
107 // try to rollback the transaction with either the
108 // ADO.NET transaction or the callbacks that managed the
109 // two phase commit transaction.
110 if (_npgsqlTx != null)
112 _npgsqlTx.Rollback();
113 _npgsqlTx.Dispose();
114 _npgsqlTx = null;
115 singlePhaseEnlistment.Aborted();
117 else if (_callbacks != null)
119 if (_rm != null)
121 _rm.RollbackWork(_callbacks.GetName());
122 singlePhaseEnlistment.Aborted();
124 else
126 _callbacks.RollbackTransaction();
127 singlePhaseEnlistment.Aborted();
129 _callbacks = null;
131 _inTransaction = false;
134 public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
136 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "SinglePhaseCommit");
137 if (_npgsqlTx != null)
139 _npgsqlTx.Commit();
140 _npgsqlTx.Dispose();
141 _npgsqlTx = null;
142 singlePhaseEnlistment.Committed();
144 else if (_callbacks != null)
146 if (_rm != null)
148 _rm.CommitWork(_callbacks.GetName());
149 singlePhaseEnlistment.Committed();
151 else
153 _callbacks.CommitTransaction();
154 singlePhaseEnlistment.Committed();
156 _callbacks = null;
158 _inTransaction = false;
161 #endregion
163 #region ITransactionPromoter Members
165 public byte[] Promote()
167 NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Promote");
168 _rm = CreateResourceManager();
169 // may not be null if Prepare or Enlist is called first
170 if (_callbacks == null)
172 _callbacks = new NpgsqlTransactionCallbacks(_connection);
174 byte[] token = _rm.Promote(_callbacks);
175 // mostly likely case for this is the transaction has been prepared.
176 if (_npgsqlTx != null)
178 // cancel the NpgsqlTransaction since this will
179 // be handled by a two phase commit.
180 _npgsqlTx.Cancel();
181 _npgsqlTx.Dispose();
182 _npgsqlTx = null;
184 return token;
187 #endregion
189 private static INpgsqlResourceManager _resourceManager;
191 private static INpgsqlResourceManager CreateResourceManager()
193 // TODO: create network proxy for resource manager
194 if (_resourceManager == null)
196 AppDomain rmDomain = AppDomain.CreateDomain("NpgsqlResourceManager", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
197 _resourceManager =
198 (INpgsqlResourceManager)
199 rmDomain.CreateInstanceAndUnwrap(typeof (NpgsqlResourceManager).Assembly.FullName,
200 typeof (NpgsqlResourceManager).FullName);
202 return _resourceManager;
203 //return new NpgsqlResourceManager();
206 private static System.Data.IsolationLevel ConvertIsolationLevel(IsolationLevel _isolationLevel)
208 switch (_isolationLevel)
210 case IsolationLevel.Chaos:
211 return System.Data.IsolationLevel.Chaos;
212 case IsolationLevel.ReadCommitted:
213 return System.Data.IsolationLevel.ReadCommitted;
214 case IsolationLevel.ReadUncommitted:
215 return System.Data.IsolationLevel.ReadUncommitted;
216 case IsolationLevel.RepeatableRead:
217 return System.Data.IsolationLevel.RepeatableRead;
218 case IsolationLevel.Serializable:
219 return System.Data.IsolationLevel.Serializable;
220 case IsolationLevel.Snapshot:
221 return System.Data.IsolationLevel.Snapshot;
222 case IsolationLevel.Unspecified:
223 default:
224 return System.Data.IsolationLevel.Unspecified;