internal OletxCommittableTransaction CreateTransaction(TransactionOptions properties) { OletxCommittableTransaction transaction = null; ITransactionShim transactionShim = null; RealOletxTransaction realOletxTransaction = null; Guid empty = Guid.Empty; OutcomeEnlistment target = null; new DistributedTransactionPermission(PermissionState.Unrestricted).Demand(); TransactionManager.ValidateIsolationLevel(properties.IsolationLevel); if (IsolationLevel.Unspecified == properties.IsolationLevel) { properties.IsolationLevel = this.configuredTransactionOptions.IsolationLevel; } properties.Timeout = TransactionManager.ValidateTimeout(properties.Timeout); this.dtcTransactionManagerLock.AcquireReaderLock(-1); try { OletxTransactionIsolationLevel isolationLevel = ConvertIsolationLevel(properties.IsolationLevel); uint timeout = System.Transactions.Oletx.DtcTransactionManager.AdjustTimeout(properties.Timeout); target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); this.dtcTransactionManager.ProxyShimFactory.BeginTransaction(timeout, isolationLevel, zero, out empty, out transactionShim); } catch (COMException exception) { ProxyException(exception); throw; } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } realOletxTransaction = new RealOletxTransaction(this, transactionShim, target, empty, isolationLevel, true); transaction = new OletxCommittableTransaction(realOletxTransaction); if (DiagnosticTrace.Information) { TransactionCreatedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), transaction.TransactionTraceId); } } finally { this.dtcTransactionManagerLock.ReleaseReaderLock(); } return(transaction); }
internal RealOletxTransaction(OletxTransactionManager transactionManager, ITransactionShim transactionShim, OutcomeEnlistment outcomeEnlistment, Guid identifier, OletxTransactionIsolationLevel oletxIsoLevel, bool isRoot) { bool flag = false; try { this.oletxTransactionManager = transactionManager; this.transactionShim = transactionShim; this.outcomeEnlistment = outcomeEnlistment; this.txGuid = identifier; this.isolationLevel = OletxTransactionManager.ConvertIsolationLevelFromProxyValue(oletxIsoLevel); this.status = TransactionStatus.Active; this.undisposedOletxTransactionCount = 0; this.phase0EnlistVolatilementContainerList = null; this.phase1EnlistVolatilementContainer = null; this.tooLateForEnlistments = false; this.internalTransaction = null; this.creationTime = DateTime.UtcNow; this.lastStateChangeTime = this.creationTime; this.internalClone = new OletxTransaction(this); if (this.outcomeEnlistment != null) { this.outcomeEnlistment.SetRealTransaction(this); } else { this.status = TransactionStatus.InDoubt; } if (DiagnosticTrace.HaveListeners) { DiagnosticTrace.TraceTransfer(this.txGuid); } flag = true; } finally { if (!flag && (this.outcomeEnlistment != null)) { this.outcomeEnlistment.UnregisterOutcomeCallback(); this.outcomeEnlistment = null; } } }
internal OletxCommittableTransaction CreateTransaction(TransactionOptions properties) { OletxCommittableTransaction transaction = null; ITransactionShim transactionShim = null; RealOletxTransaction realOletxTransaction = null; Guid empty = Guid.Empty; OutcomeEnlistment target = null; new DistributedTransactionPermission(PermissionState.Unrestricted).Demand(); TransactionManager.ValidateIsolationLevel(properties.IsolationLevel); if (IsolationLevel.Unspecified == properties.IsolationLevel) { properties.IsolationLevel = this.configuredTransactionOptions.IsolationLevel; } properties.Timeout = TransactionManager.ValidateTimeout(properties.Timeout); this.dtcTransactionManagerLock.AcquireReaderLock(-1); try { OletxTransactionIsolationLevel isolationLevel = ConvertIsolationLevel(properties.IsolationLevel); uint timeout = System.Transactions.Oletx.DtcTransactionManager.AdjustTimeout(properties.Timeout); target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); this.dtcTransactionManager.ProxyShimFactory.BeginTransaction(timeout, isolationLevel, zero, out empty, out transactionShim); } catch (COMException exception) { ProxyException(exception); throw; } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } realOletxTransaction = new RealOletxTransaction(this, transactionShim, target, empty, isolationLevel, true); transaction = new OletxCommittableTransaction(realOletxTransaction); if (DiagnosticTrace.Information) { TransactionCreatedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), transaction.TransactionTraceId); } } finally { this.dtcTransactionManagerLock.ReleaseReaderLock(); } return transaction; }
internal static void ShimNotificationCallback(object state, bool timeout) { IntPtr zero = IntPtr.Zero; ShimNotificationType none = ShimNotificationType.None; bool isSinglePhase = false; bool abortingHint = false; uint prepareInfoSize = 0; CoTaskMemHandle prepareInfo = null; bool releaseRequired = false; bool flag3 = false; IDtcProxyShimFactory factory = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransactionManager.ShimNotificationCallback"); } Thread.BeginCriticalRegion(); try { Label_003D: factory = proxyShimFactory; try { object obj2; OletxResourceManager manager2; byte[] buffer; Thread.BeginThreadAffinity(); RuntimeHelpers.PrepareConstrainedRegions(); try { factory.GetNotification(out zero, out none, out isSinglePhase, out abortingHint, out releaseRequired, out prepareInfoSize, out prepareInfo); } finally { if (releaseRequired) { if (HandleTable.FindHandle(zero) is OletxInternalResourceManager) { processingTmDown = true; Monitor.Enter(proxyShimFactory); } else { releaseRequired = false; } factory.ReleaseNotificationLock(); } Thread.EndThreadAffinity(); } if (processingTmDown) { lock (proxyShimFactory) { } } if (none != ShimNotificationType.None) { obj2 = HandleTable.FindHandle(zero); switch (none) { case ShimNotificationType.Phase0RequestNotify: try { OletxPhase0VolatileEnlistmentContainer container5 = obj2 as OletxPhase0VolatileEnlistmentContainer; if (container5 != null) { DiagnosticTrace.SetActivityId(container5.TransactionIdentifier); container5.Phase0Request(abortingHint); } else { OletxEnlistment enlistment8 = obj2 as OletxEnlistment; if (enlistment8 != null) { DiagnosticTrace.SetActivityId(enlistment8.TransactionIdentifier); enlistment8.Phase0Request(abortingHint); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } break; case ShimNotificationType.VoteRequestNotify: break; case ShimNotificationType.PrepareRequestNotify: goto Label_02B0; case ShimNotificationType.CommitRequestNotify: goto Label_031A; case ShimNotificationType.AbortRequestNotify: goto Label_0358; case ShimNotificationType.CommittedNotify: try { OutcomeEnlistment enlistment7 = obj2 as OutcomeEnlistment; if (enlistment7 != null) { DiagnosticTrace.SetActivityId(enlistment7.TransactionIdentifier); enlistment7.Committed(); } else { OletxPhase1VolatileEnlistmentContainer container3 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container3 != null) { DiagnosticTrace.SetActivityId(container3.TransactionIdentifier); container3.Committed(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } goto Label_0203; case ShimNotificationType.AbortedNotify: goto Label_0203; case ShimNotificationType.InDoubtNotify: goto Label_0251; case ShimNotificationType.EnlistmentTmDownNotify: goto Label_0396; case ShimNotificationType.ResourceManagerTmDownNotify: goto Label_03CD; default: goto Label_0410; } OletxPhase1VolatileEnlistmentContainer container4 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container4 != null) { DiagnosticTrace.SetActivityId(container4.TransactionIdentifier); container4.VoteRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; Label_0203 :; try { OutcomeEnlistment enlistment6 = obj2 as OutcomeEnlistment; if (enlistment6 != null) { DiagnosticTrace.SetActivityId(enlistment6.TransactionIdentifier); enlistment6.Aborted(); } else { OletxPhase1VolatileEnlistmentContainer container2 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container2 != null) { DiagnosticTrace.SetActivityId(container2.TransactionIdentifier); container2.Aborted(); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0251 :; try { OutcomeEnlistment enlistment5 = obj2 as OutcomeEnlistment; if (enlistment5 != null) { DiagnosticTrace.SetActivityId(enlistment5.TransactionIdentifier); enlistment5.InDoubt(); } else { OletxPhase1VolatileEnlistmentContainer container = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container != null) { DiagnosticTrace.SetActivityId(container.TransactionIdentifier); container.InDoubt(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_02B0: buffer = new byte[prepareInfoSize]; Marshal.Copy(prepareInfo.DangerousGetHandle(), buffer, 0, Convert.ToInt32(prepareInfoSize)); bool flag2 = true; try { OletxEnlistment enlistment4 = obj2 as OletxEnlistment; if (enlistment4 != null) { DiagnosticTrace.SetActivityId(enlistment4.TransactionIdentifier); flag2 = enlistment4.PrepareRequest(isSinglePhase, buffer); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { if (flag2) { HandleTable.FreeHandle(zero); } } Label_031A :; try { OletxEnlistment enlistment3 = obj2 as OletxEnlistment; if (enlistment3 != null) { DiagnosticTrace.SetActivityId(enlistment3.TransactionIdentifier); enlistment3.CommitRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0358 :; try { OletxEnlistment enlistment2 = obj2 as OletxEnlistment; if (enlistment2 != null) { DiagnosticTrace.SetActivityId(enlistment2.TransactionIdentifier); enlistment2.AbortRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0396 :; try { OletxEnlistment enlistment = obj2 as OletxEnlistment; if (enlistment != null) { DiagnosticTrace.SetActivityId(enlistment.TransactionIdentifier); enlistment.TMDown(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_03CD: manager2 = obj2 as OletxResourceManager; try { if (manager2 != null) { manager2.TMDown(); } else { OletxInternalResourceManager manager = obj2 as OletxInternalResourceManager; if (manager != null) { manager.TMDown(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0410: Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } finally { if (prepareInfo != null) { prepareInfo.Close(); } if (releaseRequired) { releaseRequired = false; processingTmDown = false; Monitor.Exit(proxyShimFactory); } } Label_0444: if (none != ShimNotificationType.None) { goto Label_003D; } flag3 = true; } finally { if (releaseRequired) { releaseRequired = false; processingTmDown = false; Monitor.Exit(proxyShimFactory); } if (!flag3 && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } Thread.EndCriticalRegion(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransactionManager.ShimNotificationCallback"); } }
public static Transaction GetTransactionFromExportCookie(byte[] cookie) { if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } if (cookie == null) { throw new ArgumentNullException("cookie"); } if (cookie.Length < 0x20) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "cookie"); } if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } byte[] destinationArray = new byte[cookie.Length]; Array.Copy(cookie, destinationArray, cookie.Length); cookie = destinationArray; Transaction transaction = null; ITransactionShim transactionShim = null; Guid empty = Guid.Empty; OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment target = null; OletxTransaction oletx = null; byte[] b = new byte[0x10]; for (int i = 0; i < b.Length; i++) { b[i] = cookie[i + 0x10]; } Guid transactionIdentifier = new Guid(b); transaction = TransactionManager.FindPromotedTransaction(transactionIdentifier); if (null != transaction) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } return transaction; } RealOletxTransaction realOletxTransaction = null; OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager; distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1); try { target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.Import(Convert.ToUInt32(cookie.Length), cookie, zero, out empty, out isolationLevel, out transactionShim); } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } finally { distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock(); } realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false); oletx = new OletxTransaction(realOletxTransaction); transaction = TransactionManager.FindOrCreatePromotedTransaction(transactionIdentifier, oletx); if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } return transaction; }
public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative) { OletxXactTransInfo info; if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } bool flag = false; ITransactionShim transactionShim = null; Guid empty = Guid.Empty; OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment target = null; RealOletxTransaction realOletxTransaction = null; OletxTransaction oletx = null; if (transactionNative == null) { throw new ArgumentNullException("transactionNative"); } Transaction transaction = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc"); } ITransactionNativeInternal internal2 = transactionNative as ITransactionNativeInternal; if (internal2 == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "transactionNative"); } try { internal2.GetTransactionInfo(out info); } catch (COMException exception2) { if (System.Transactions.Oletx.NativeMethods.XACT_E_NOTRANSACTION != exception2.ErrorCode) { throw; } flag = true; info.uow = Guid.Empty; } OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager; if (!flag) { transaction = TransactionManager.FindPromotedTransaction(info.uow); if (null != transaction) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtcTransaction"); } return transaction; } distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1); try { target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(transactionNative, zero, out empty, out isolationLevel, out transactionShim); } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw; } finally { distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock(); } realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false); oletx = new OletxTransaction(realOletxTransaction); transaction = TransactionManager.FindOrCreatePromotedTransaction(info.uow, oletx); } else { realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, null, null, empty, OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, false); oletx = new OletxTransaction(realOletxTransaction); transaction = new Transaction(oletx); TransactionManager.FireDistributedTransactionStarted(transaction); oletx.savedLtmPromotedTransaction = transaction; InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc"); } return transaction; }
internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken(byte[] propagationToken) { OutcomeEnlistment enlistment; ITransactionShim transactionShim = null; OletxTransactionIsolationLevel level; Guid guid; if (propagationToken == null) { throw new ArgumentNullException("propagationToken"); } if (propagationToken.Length < 0x18) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "propagationToken"); } byte[] destinationArray = new byte[propagationToken.Length]; Array.Copy(propagationToken, destinationArray, propagationToken.Length); propagationToken = destinationArray; OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager; distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1); try { enlistment = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(enlistment); distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction(Convert.ToUInt32(propagationToken.Length), propagationToken, zero, out guid, out level, out transactionShim); } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } finally { distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock(); } return new OletxTransaction(new RealOletxTransaction(distributedTransactionManager, transactionShim, enlistment, guid, level, false)); }
// Common constructor used by all types of constructors // Create a clean and fresh transaction. internal RealOletxTransaction(OletxTransactionManager transactionManager, ITransactionShim transactionShim, OutcomeEnlistment outcomeEnlistment, Guid identifier, OletxTransactionIsolationLevel oletxIsoLevel, bool isRoot ) { bool successful = false; try { // initialize the member fields this.oletxTransactionManager = transactionManager; this.transactionShim = transactionShim; this.outcomeEnlistment = outcomeEnlistment; this.txGuid = identifier; this.isolationLevel = OletxTransactionManager.ConvertIsolationLevelFromProxyValue( oletxIsoLevel ); this.status = TransactionStatus.Active; this.undisposedOletxTransactionCount = 0; this.phase0EnlistVolatilementContainerList = null; this.phase1EnlistVolatilementContainer = null; this.tooLateForEnlistments = false; this.internalTransaction = null; this.creationTime = DateTime.UtcNow; this.lastStateChangeTime = this.creationTime; // Connect this object with the OutcomeEnlistment. this.internalClone = new OletxTransaction( this ); // We have have been created without an outcome enlistment if it was too late to create // a clone from the ITransactionNative that we were created from. if ( null != this.outcomeEnlistment ) { this.outcomeEnlistment.SetRealTransaction( this ); } else { this.status = TransactionStatus.InDoubt; } if ( DiagnosticTrace.HaveListeners ) { DiagnosticTrace.TraceTransfer(this.txGuid); } successful = true; } finally { if (!successful) { if (this.outcomeEnlistment != null) { this.outcomeEnlistment.UnregisterOutcomeCallback(); this.outcomeEnlistment = null; } } } }
public static Transaction GetTransactionFromDtcTransaction( IDtcTransaction transactionNative ) { if ( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); bool tooLate = false; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment outcomeEnlistment = null; RealOletxTransaction realTx = null; OletxTransaction oleTx = null; if ( null == transactionNative ) { throw new ArgumentNullException( "transactionNative" ); } Transaction transaction = null; if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtc" ); } // Let's get the guid of the transaction from the proxy to see if we already // have an object. ITransactionNativeInternal myTransactionNative = transactionNative as ITransactionNativeInternal; if ( null == myTransactionNative ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "transactionNative" ); } OletxXactTransInfo xactInfo; try { myTransactionNative.GetTransactionInfo( out xactInfo ); } catch ( COMException ex ) { if ( Oletx.NativeMethods.XACT_E_NOTRANSACTION != ex.ErrorCode ) { throw; } // If we get here, the transaction has appraently already been committed or aborted. Allow creation of the // OletxTransaction, but it will be marked with a status of InDoubt and attempts to get its Identifier // property will result in a TransactionException. tooLate = true; xactInfo.uow = Guid.Empty; } OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; if ( ! tooLate ) { // First check to see if there is a promoted LTM transaction with the same ID. If there // is, just return that. transaction = TransactionManager.FindPromotedTransaction( xactInfo.uow ); if ( null != transaction ) { if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtcTransaction" ); } return transaction; } // We need to create a new RealOletxTransaction... oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim( transactionNative, outcomeEnlistmentHandle, out txIdentifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); throw; } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } // We need to create a new RealOletxTransaction. realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, false ); oleTx = new OletxTransaction( realTx ); // If a transaction is found then FindOrCreate will Dispose the oletx // created. transaction = TransactionManager.FindOrCreatePromotedTransaction( xactInfo.uow, oleTx ); } else { // It was too late to do a clone of the provided ITransactionNative, so we are just going to // create a RealOletxTransaction without a transaction shim or outcome enlistment. realTx = new RealOletxTransaction( oletxTm, null, null, txIdentifier, OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, false ); oleTx = new OletxTransaction( realTx ); transaction = new Transaction( oleTx ); TransactionManager.FireDistributedTransactionStarted( transaction ); oleTx.savedLtmPromotedTransaction = transaction; InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt); } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtc" ); } return transaction; }
internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken( byte[] propagationToken ) { Guid identifier; OletxTransactionIsolationLevel oletxIsoLevel; OutcomeEnlistment outcomeEnlistment; ITransactionShim transactionShim = null; if ( null == propagationToken ) { throw new ArgumentNullException( "propagationToken" ); } if ( propagationToken.Length < 24 ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" ); } byte[] propagationTokenCopy = new byte[propagationToken.Length]; Array.Copy(propagationToken, propagationTokenCopy, propagationToken.Length); propagationToken = propagationTokenCopy; // First we need to create an OletxTransactionManager from Config. OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction( Convert.ToUInt32(propagationToken.Length), propagationToken, outcomeEnlistmentHandle, out identifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); // We are unsure of what the exception may mean. It is possible that // we could get E_FAIL when trying to contact a transaction manager that is // being blocked by a fire wall. On the other hand we may get a COMException // based on bad data. The more common situation is that the data is fine // (since it is generated by Microsoft code) and the problem is with // communication. So in this case we default for unknown exceptions to // assume that the problem is with communication. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } RealOletxTransaction realTx = null; realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, identifier, oletxIsoLevel, false ); return new OletxTransaction( realTx ); }
public static Transaction GetTransactionFromExportCookie( byte[] cookie ) { if ( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( null == cookie ) { throw new ArgumentNullException( "cookie" ); } if ( cookie.Length < 32 ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "cookie" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } byte[] cookieCopy = new byte[cookie.Length]; Array.Copy(cookie, cookieCopy, cookie.Length); cookie = cookieCopy; Transaction transaction = null; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment outcomeEnlistment = null; OletxTransaction oleTx = null; // Extract the transaction guid from the propagation token to see if we already have a // transaction object for the transaction. byte[] guidByteArray = new byte[16]; for (int i = 0; i < guidByteArray.Length; i++ ) { // In a cookie, the transaction guid is preceeded by a signature guid. guidByteArray[i] = cookie[i + 16]; } Guid txId = new Guid( guidByteArray ); // First check to see if there is a promoted LTM transaction with the same ID. If there // is, just return that. transaction = TransactionManager.FindPromotedTransaction( txId ); if ( null != transaction ) { if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } return transaction; } // We need to create a new transaction RealOletxTransaction realTx = null; OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.Import( Convert.ToUInt32(cookie.Length), cookie, outcomeEnlistmentHandle, out txIdentifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); // We are unsure of what the exception may mean. It is possible that // we could get E_FAIL when trying to contact a transaction manager that is // being blocked by a fire wall. On the other hand we may get a COMException // based on bad data. The more common situation is that the data is fine // (since it is generated by Microsoft code) and the problem is with // communication. So in this case we default for unknown exceptions to // assume that the problem is with communication. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } // We need to create a new RealOletxTransaction. realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, false ); // Now create the associated OletxTransaction. oleTx = new OletxTransaction( realTx ); // If a transaction is found then FindOrCreate will Dispose the oletx // created. transaction = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } return transaction; }
internal static void ShimNotificationCallback(object state, bool timeout) { // First we need to get the notification from the shim factory. IntPtr enlistmentHandleIntPtr = IntPtr.Zero; ShimNotificationType shimNotificationType = ShimNotificationType.None; bool isSinglePhase = false; bool abortingHint = false; UInt32 prepareInfoSize = 0; CoTaskMemHandle prepareInfoBuffer = null; bool holdingNotificationLock = false; bool cleanExit = false; IDtcProxyShimFactory localProxyShimFactory = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxTransactionManager.ShimNotificationCallback" ); } // This lock doesn't really protect any of our data. It is here so that if an exception occurs // while calling out to the app, we get an escalation to AppDomainUnload. Thread.BeginCriticalRegion(); try { do { // Take a local copy of the proxyShimFactory because if we get an RM TMDown notification, // we will still hold the critical section in that factory, but processing of the TMDown will // cause replacement of the OletxTransactionManager.proxyShimFactory. localProxyShimFactory = OletxTransactionManager.proxyShimFactory; try { Thread.BeginThreadAffinity(); RuntimeHelpers.PrepareConstrainedRegions(); try { localProxyShimFactory.GetNotification( out enlistmentHandleIntPtr, out shimNotificationType, out isSinglePhase, out abortingHint, out holdingNotificationLock, out prepareInfoSize, out prepareInfoBuffer ); } finally { if (holdingNotificationLock) { if ((HandleTable.FindHandle(enlistmentHandleIntPtr)) is OletxInternalResourceManager) { // In this case we know that the TM has gone down and we need to exchange // the native lock for a managed lock. processingTmDown = true; #pragma warning disable 0618 //@ System.Threading.Monitor.Enter(OletxTransactionManager.proxyShimFactory); #pragma warning restore 0618 } else { holdingNotificationLock = false; } localProxyShimFactory.ReleaseNotificationLock(); } Thread.EndThreadAffinity(); } // If a TM down is being processed it is possible that the native lock // has been exchanged for a managed lock. In that case we need to attempt // to take a lock to hold up processing more events until the TM down // processing is complete. if (processingTmDown) { lock (OletxTransactionManager.proxyShimFactory) { // We don't do any work under this lock just make sure that we // can take it. } } if (ShimNotificationType.None != shimNotificationType) { Object target = HandleTable.FindHandle(enlistmentHandleIntPtr); // Next, based on the notification type, cast the Handle accordingly and make // the appropriate call on the enlistment. switch (shimNotificationType) { case ShimNotificationType.Phase0RequestNotify: { try { OletxPhase0VolatileEnlistmentContainer ph0VolEnlistContainer = target as OletxPhase0VolatileEnlistmentContainer; if (null != ph0VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph0VolEnlistContainer.TransactionIdentifier); //CSDMain 91509 - We now synchronize this call with the AddDependentClone call in RealOleTxTransaction ph0VolEnlistContainer.Phase0Request(abortingHint); } else { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.Phase0Request(abortingHint); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.VoteRequestNotify: { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.VoteRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } break; } case ShimNotificationType.CommittedNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.Committed(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.Committed(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.AbortedNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.Aborted(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.Aborted(); } // else // Voters may receive notifications even // in cases where they therwise respond // negatively to the vote request. It is // also not guaranteed that we will get a // notification if we do respond negatively. // The only safe thing to do is to free the // Handle when we abort the transaction // with a voter. These two things together // mean that we cannot guarantee that this // Handle will be alive when we get this // notification. } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.InDoubtNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.InDoubt(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.InDoubt(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.PrepareRequestNotify: { byte[] prepareInfo = new byte[prepareInfoSize]; Marshal.Copy(prepareInfoBuffer.DangerousGetHandle(), prepareInfo, 0, Convert.ToInt32(prepareInfoSize)); bool enlistmentDone = true; try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistmentDone = enlistment.PrepareRequest( isSinglePhase, prepareInfo ); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { if (enlistmentDone) { HandleTable.FreeHandle(enlistmentHandleIntPtr); } } break; } case ShimNotificationType.CommitRequestNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.CommitRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.AbortRequestNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.AbortRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.EnlistmentTmDownNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.TMDown(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.ResourceManagerTmDownNotify: { OletxResourceManager resourceManager = target as OletxResourceManager; try { if (null != resourceManager) { resourceManager.TMDown(); } else { OletxInternalResourceManager internalResourceManager = target as OletxInternalResourceManager; if (null != internalResourceManager) { internalResourceManager.TMDown(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { HandleTable.FreeHandle(enlistmentHandleIntPtr); } // Note that we don't free the gchandle on the OletxResourceManager. These objects // are not going to go away. break; } default: { Environment.FailFast(SR.GetString(SR.InternalError)); break; } } } } finally { if (null != prepareInfoBuffer) { prepareInfoBuffer.Close(); } if (holdingNotificationLock) { holdingNotificationLock = false; processingTmDown = false; System.Threading.Monitor.Exit(OletxTransactionManager.proxyShimFactory); } } }while (ShimNotificationType.None != shimNotificationType); cleanExit = true; } finally { if (holdingNotificationLock) { holdingNotificationLock = false; processingTmDown = false; System.Threading.Monitor.Exit(OletxTransactionManager.proxyShimFactory); } if (!cleanExit && enlistmentHandleIntPtr != IntPtr.Zero) { HandleTable.FreeHandle(enlistmentHandleIntPtr); } Thread.EndCriticalRegion(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxTransactionManager.ShimNotificationCallback" ); } }
internal OletxCommittableTransaction CreateTransaction( TransactionOptions properties ) { OletxCommittableTransaction tx = null; RealOletxTransaction realTransaction = null; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OutcomeEnlistment outcomeEnlistment = null; // Demand the distributed transation permission to create one of // these. DistributedTransactionPermission txPerm = new DistributedTransactionPermission(PermissionState.Unrestricted); txPerm.Demand(); TransactionManager.ValidateIsolationLevel(properties.IsolationLevel); // Never create a transaction with an IsolationLevel of Unspecified. if (IsolationLevel.Unspecified == properties.IsolationLevel) { properties.IsolationLevel = configuredTransactionOptions.IsolationLevel; } properties.Timeout = TransactionManager.ValidateTimeout(properties.Timeout); this.dtcTransactionManagerLock.AcquireReaderLock(-1); try { // OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionManager.ConvertIsolationLevel(properties.IsolationLevel); UInt32 oletxTimeout = DtcTransactionManager.AdjustTimeout(properties.Timeout); outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle(outcomeEnlistment); dtcTransactionManager.ProxyShimFactory.BeginTransaction( oletxTimeout, oletxIsoLevel, outcomeEnlistmentHandle, out txIdentifier, out transactionShim ); } catch (COMException ex) { OletxTransactionManager.ProxyException(ex); throw; } finally { if (transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero) { HandleTable.FreeHandle(outcomeEnlistmentHandle); } } realTransaction = new RealOletxTransaction( this, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, true ); tx = new OletxCommittableTransaction(realTransaction); if (DiagnosticTrace.Information) { TransactionCreatedTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), tx.TransactionTraceId ); } } finally { this.dtcTransactionManagerLock.ReleaseReaderLock(); } return(tx); }
internal OletxCommittableTransaction CreateTransaction( TransactionOptions properties ) { OletxCommittableTransaction tx = null; RealOletxTransaction realTransaction = null; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OutcomeEnlistment outcomeEnlistment = null; // Demand the distributed transation permission to create one of // these. DistributedTransactionPermission txPerm = new DistributedTransactionPermission( PermissionState.Unrestricted ); txPerm.Demand(); TransactionManager.ValidateIsolationLevel( properties.IsolationLevel ); // Never create a transaction with an IsolationLevel of Unspecified. if ( IsolationLevel.Unspecified == properties.IsolationLevel ) { properties.IsolationLevel = configuredTransactionOptions.IsolationLevel; } properties.Timeout = TransactionManager.ValidateTimeout( properties.Timeout ); this.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { // OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionManager.ConvertIsolationLevel( properties.IsolationLevel ); UInt32 oletxTimeout = DtcTransactionManager.AdjustTimeout( properties.Timeout ); outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); dtcTransactionManager.ProxyShimFactory.BeginTransaction( oletxTimeout, oletxIsoLevel, outcomeEnlistmentHandle, out txIdentifier, out transactionShim ); } catch ( COMException ex ) { OletxTransactionManager.ProxyException( ex ); throw; } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } realTransaction = new RealOletxTransaction( this, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, true ); tx = new OletxCommittableTransaction( realTransaction ); if ( DiagnosticTrace.Information ) { TransactionCreatedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), tx.TransactionTraceId ); } } finally { this.dtcTransactionManagerLock.ReleaseReaderLock(); } return tx; }