internal OletxVolatileEnlistment(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) : base(null, oletxTransaction) { this.iEnlistmentNotification = enlistmentNotification; this.enlistDuringPrepareRequired = (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None; this.container = null; this.pendingOutcome = TransactionStatus.Active; if (DiagnosticTrace.Information) { EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Volatile, enlistmentOptions); } }
internal InternalTransaction(Transaction outcomeSource, OletxTransaction distributedTx) { if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } this.promotedTransaction = distributedTx; this.absoluteTimeout = 0x7fffffffffffffffL; this.outcomeSource = outcomeSource; this.transactionHash = TransactionManager.TransactionTable.Add(this); TransactionState._TransactionStateNonCommittablePromoted.EnterState(this); this.promoteState = TransactionState._TransactionStateNonCommittablePromoted; }
public OletxBaseEnlistment(OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction) { this.oletxResourceManager = oletxResourceManager; this.oletxTransaction = oletxTransaction; if (oletxTransaction != null) { this.enlistmentId = oletxTransaction.realOletxTransaction.enlistmentCount++; this.transactionGuidString = oletxTransaction.realOletxTransaction.TxGuid.ToString(); } else { this.transactionGuidString = Guid.Empty.ToString(); } this.traceIdentifier = EnlistmentTraceIdentifier.Empty; }
internal static Transaction FindOrCreatePromotedTransaction( Guid transactionIdentifier, Oletx.OletxTransaction oletx ) { Transaction tx = null; Hashtable promotedTransactionTable = PromotedTransactionTable; lock (promotedTransactionTable) { WeakReference weakRef = (WeakReference)promotedTransactionTable[transactionIdentifier]; if (null != weakRef) { tx = weakRef.Target as Transaction; if (null != tx) { // If we found a transaction then dispose the oletx oletx.Dispose(); return(tx.InternalClone()); } else // an old, moldy weak reference. Let's get rid of it. { lock ( promotedTransactionTable ) { promotedTransactionTable.Remove(transactionIdentifier); } } } tx = new Transaction(oletx); // Since we are adding this reference to the table create an object that will clean that // entry up. tx.internalTransaction.finalizedObject = new FinalizedObject(tx.internalTransaction, oletx.Identifier); weakRef = new WeakReference(tx, false); promotedTransactionTable[oletx.Identifier] = weakRef; } oletx.savedLtmPromotedTransaction = tx; TransactionManager.FireDistributedTransactionStarted(tx); return(tx); }
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; } } }
// Construct an internal transaction internal InternalTransaction(Transaction outcomeSource, Oletx.OletxTransaction distributedTx) { if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } this.promotedTransaction = distributedTx; this.absoluteTimeout = long.MaxValue; // Store the initial creater as it will be the source of outcome events this.outcomeSource = outcomeSource; // Initialize the hash this.transactionHash = TransactionManager.TransactionTable.Add(this); // Start the transaction off as active TransactionState._TransactionStateNonCommittablePromoted.EnterState(this); // Until otherwise noted this transaction uses normal promotion. this.promoteState = TransactionState._TransactionStateNonCommittablePromoted; }
internal static byte[] GetTransmitterPropagationToken(OletxTransaction oletxTx) { CoTaskMemHandle propgationToken = null; byte[] destination = null; uint propagationTokeSize = 0; try { oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken(out propagationTokeSize, out propgationToken); destination = new byte[propagationTokeSize]; Marshal.Copy(propgationToken.DangerousGetHandle(), destination, 0, Convert.ToInt32(propagationTokeSize)); } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw; } finally { if (propgationToken != null) { propgationToken.Close(); } } return destination; }
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 IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { OletxVolatileEnlistment enlistment = null; bool flag2 = false; bool flag = false; OletxPhase0VolatileEnlistmentContainer target = null; OletxPhase1VolatileEnlistmentContainer container = null; IntPtr zero = IntPtr.Zero; IVoterBallotShim voterBallotShim = null; IPhase0EnlistmentShim shim = null; bool flag3 = false; RuntimeHelpers.PrepareConstrainedRegions(); try { lock (this) { enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction); if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { if (this.phase0EnlistVolatilementContainerList == null) { this.phase0EnlistVolatilementContainerList = new ArrayList(1); } if (this.phase0EnlistVolatilementContainerList.Count == 0) { target = new OletxPhase0VolatileEnlistmentContainer(this); flag = true; } else { target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer; if (!target.NewEnlistmentsAllowed) { target = new OletxPhase0VolatileEnlistmentContainer(this); flag = true; } else { flag = false; } } if (flag) { zero = HandleTable.AllocHandle(target); } } else if (this.phase1EnlistVolatilementContainer == null) { flag2 = true; container = new OletxPhase1VolatileEnlistmentContainer(this) { voterHandle = HandleTable.AllocHandle(container) }; } else { flag2 = false; container = this.phase1EnlistVolatilementContainer; } try { if (flag) { lock (target) { this.transactionShim.Phase0Enlist(zero, out shim); target.Phase0EnlistmentShim = shim; } } if (flag2) { this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim); flag3 = true; container.VoterBallotShim = voterBallotShim; } if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { target.AddEnlistment(enlistment); if (flag) { this.phase0EnlistVolatilementContainerList.Add(target); } return(enlistment); } container.AddEnlistment(enlistment); if (flag2) { this.phase1EnlistVolatilementContainer = container; } return(enlistment); } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw; } return(enlistment); } } finally { if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null)) { HandleTable.FreeHandle(zero); } if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2)) { HandleTable.FreeHandle(container.voterHandle); } } return(enlistment); }
internal IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { OletxVolatileEnlistment enlistment = null; bool flag2 = false; bool flag = false; OletxPhase0VolatileEnlistmentContainer target = null; OletxPhase1VolatileEnlistmentContainer container = null; IntPtr zero = IntPtr.Zero; IVoterBallotShim voterBallotShim = null; IPhase0EnlistmentShim shim = null; bool flag3 = false; RuntimeHelpers.PrepareConstrainedRegions(); try { lock (this) { enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction); if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { if (this.phase0EnlistVolatilementContainerList == null) { this.phase0EnlistVolatilementContainerList = new ArrayList(1); } if (this.phase0EnlistVolatilementContainerList.Count == 0) { target = new OletxPhase0VolatileEnlistmentContainer(this); flag = true; } else { target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer; if (!target.NewEnlistmentsAllowed) { target = new OletxPhase0VolatileEnlistmentContainer(this); flag = true; } else { flag = false; } } if (flag) { zero = HandleTable.AllocHandle(target); } } else if (this.phase1EnlistVolatilementContainer == null) { flag2 = true; container = new OletxPhase1VolatileEnlistmentContainer(this) { voterHandle = HandleTable.AllocHandle(container) }; } else { flag2 = false; container = this.phase1EnlistVolatilementContainer; } try { if (flag) { lock (target) { this.transactionShim.Phase0Enlist(zero, out shim); target.Phase0EnlistmentShim = shim; } } if (flag2) { this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim); flag3 = true; container.VoterBallotShim = voterBallotShim; } if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { target.AddEnlistment(enlistment); if (flag) { this.phase0EnlistVolatilementContainerList.Add(target); } return enlistment; } container.AddEnlistment(enlistment); if (flag2) { this.phase1EnlistVolatilementContainer = container; } return enlistment; } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw; } return enlistment; } } finally { if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null)) { HandleTable.FreeHandle(zero); } if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2)) { HandleTable.FreeHandle(container.voterHandle); } } return enlistment; }
internal OletxEnlistment EnlistDurable(OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions) { IResourceManagerShim resourceManagerShim = null; IPhase0EnlistmentShim shim2 = null; IEnlistmentShim enlistmentShim = null; IntPtr zero = IntPtr.Zero; bool flag3 = false; bool flag2 = false; OletxEnlistment target = new OletxEnlistment(canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction); bool flag = false; RuntimeHelpers.PrepareConstrainedRegions(); try { if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.IncrementUndecidedEnlistments(); flag2 = true; } } lock (target) { RuntimeHelpers.PrepareConstrainedRegions(); try { resourceManagerShim = this.ResourceManagerShim; if (resourceManagerShim == null) { throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), null); } if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { zero = HandleTable.AllocHandle(target); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(zero, out shim2); flag3 = true; } target.Phase0EnlistmentShim = shim2; } target.phase1Handle = HandleTable.AllocHandle(target); resourceManagerShim.Enlist(oletxTransaction.RealTransaction.TransactionShim, target.phase1Handle, out enlistmentShim); target.EnlistmentShim = enlistmentShim; } catch (COMException exception) { if (System.Transactions.Oletx.NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == exception.ErrorCode) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxTooManyEnlistments"), exception); } OletxTransactionManager.ProxyException(exception); throw; } finally { if (target.EnlistmentShim == null) { if ((zero != IntPtr.Zero) && !flag3) { HandleTable.FreeHandle(zero); } if (target.phase1Handle != IntPtr.Zero) { HandleTable.FreeHandle(target.phase1Handle); } } } } flag = true; } finally { if ((!flag && ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)) && flag2) { oletxTransaction.RealTransaction.DecrementUndecidedEnlistments(); } } return target; }
internal OletxVolatileEnlistment( IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction ) : base( null, oletxTransaction ) { this.iEnlistmentNotification = enlistmentNotification; this.enlistDuringPrepareRequired = (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0; // We get a container when we are asked to vote. this.container = null; pendingOutcome = TransactionStatus.Active; if ( DiagnosticTrace.Information ) { EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, EnlistmentType.Volatile, enlistmentOptions ); } }
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 byte[] GetTransmitterPropagationToken( OletxTransaction oletxTx ) { byte[] propagationToken = null; CoTaskMemHandle propagationTokenBuffer = null; UInt32 tokenSize = 0; try { oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken( out tokenSize, out propagationTokenBuffer ); propagationToken = new byte[tokenSize]; Marshal.Copy( propagationTokenBuffer.DangerousGetHandle(), propagationToken, 0, Convert.ToInt32(tokenSize) ); } catch (COMException comException) { OletxTransactionManager.ProxyException( comException ); throw; } finally { if ( null != propagationTokenBuffer ) { propagationTokenBuffer.Close(); } } return propagationToken; }
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 IPromotedEnlistment EnlistVolatile(ISinglePhaseNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { return(this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction)); }
// Construct an internal transaction internal InternalTransaction( Transaction outcomeSource, Oletx.OletxTransaction distributedTx ) { if ( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); this.promotedTransaction = distributedTx; this.absoluteTimeout = long.MaxValue; // Store the initial creater as it will be the source of outcome events this.outcomeSource = outcomeSource; // Initialize the hash this.transactionHash = TransactionManager.TransactionTable.Add( this ); // Start the transaction off as active TransactionState._TransactionStateNonCommittablePromoted.EnterState( this ); // Until otherwise noted this transaction uses normal promotion. this.promoteState = TransactionState._TransactionStateNonCommittablePromoted; }
internal OletxEnlistment(bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, Guid transactionGuid, EnlistmentOptions enlistmentOptions, OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction) : base(oletxResourceManager, oletxTransaction) { this.transactionGuid = Guid.Empty; this.phase1Handle = IntPtr.Zero; this.enlistmentShim = null; this.phase0Shim = null; this.canDoSinglePhase = canDoSinglePhase; this.iEnlistmentNotification = enlistmentNotification; this.state = OletxEnlistmentState.Active; this.transactionGuid = transactionGuid; this.proxyPrepareInfoByteArray = null; if (DiagnosticTrace.Information) { EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Durable, enlistmentOptions); } base.AddToEnlistmentTable(); }
internal IPromotedEnlistment EnlistVolatile(ISinglePhaseNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { return this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction); }
internal OletxEnlistment( bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, Guid transactionGuid, EnlistmentOptions enlistmentOptions, OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction ) : base( oletxResourceManager, oletxTransaction ) { Guid myGuid = Guid.Empty; // This will get set later by the creator of this object after it // has enlisted with the proxy. this.enlistmentShim = null; this.phase0Shim = null; this.canDoSinglePhase = canDoSinglePhase; this.iEnlistmentNotification = enlistmentNotification; this.state = OletxEnlistmentState.Active; this.transactionGuid = transactionGuid; this.proxyPrepareInfoByteArray = null; if ( DiagnosticTrace.Information ) { EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, EnlistmentType.Durable, enlistmentOptions ); } // Always do this last incase anything earlier fails. AddToEnlistmentTable(); }
internal OletxEnlistment EnlistDurable(OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions) { IResourceManagerShim resourceManagerShim = null; IPhase0EnlistmentShim shim2 = null; IEnlistmentShim enlistmentShim = null; IntPtr zero = IntPtr.Zero; bool flag3 = false; bool flag2 = false; OletxEnlistment target = new OletxEnlistment(canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction); bool flag = false; RuntimeHelpers.PrepareConstrainedRegions(); try { if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.IncrementUndecidedEnlistments(); flag2 = true; } } lock (target) { RuntimeHelpers.PrepareConstrainedRegions(); try { resourceManagerShim = this.ResourceManagerShim; if (resourceManagerShim == null) { throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), null); } if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None) { zero = HandleTable.AllocHandle(target); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(zero, out shim2); flag3 = true; } target.Phase0EnlistmentShim = shim2; } target.phase1Handle = HandleTable.AllocHandle(target); resourceManagerShim.Enlist(oletxTransaction.RealTransaction.TransactionShim, target.phase1Handle, out enlistmentShim); target.EnlistmentShim = enlistmentShim; } catch (COMException exception) { if (System.Transactions.Oletx.NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == exception.ErrorCode) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxTooManyEnlistments"), exception); } OletxTransactionManager.ProxyException(exception); throw; } finally { if (target.EnlistmentShim == null) { if ((zero != IntPtr.Zero) && !flag3) { HandleTable.FreeHandle(zero); } if (target.phase1Handle != IntPtr.Zero) { HandleTable.FreeHandle(target.phase1Handle); } } } } flag = true; } finally { if ((!flag && ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)) && flag2) { oletxTransaction.RealTransaction.DecrementUndecidedEnlistments(); } } return(target); }
internal IPromotedEnlistment EnlistVolatile( IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction ) { IPromotedEnlistment enlistment = CommonEnlistVolatile( enlistmentNotification, enlistmentOptions, oletxTransaction ); return enlistment; }
// 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; } } } }
internal Transaction(OletxTransaction oleTransaction) { this.isoLevel = oleTransaction.IsolationLevel; this.internalTransaction = new InternalTransaction(this, oleTransaction); this.cloneId = Interlocked.Increment(ref this.internalTransaction.cloneCount); }
internal OletxEnlistment EnlistDurable( OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions ) { IResourceManagerShim localResourceManagerShim = null; Debug.Assert( null != oletxTransaction, "Argument is null" ); Debug.Assert( null != enlistmentNotification, "Argument is null" ); IEnlistmentShim enlistmentShim = null; IPhase0EnlistmentShim phase0Shim = null; Guid txUow = Guid.Empty; IntPtr handlePhase0 = IntPtr.Zero; bool phase0EnlistSucceeded = false; bool undecidedEnlistmentsIncremented = false; // Create our enlistment object. OletxEnlistment enlistment = new OletxEnlistment( canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction ); bool enlistmentSucceeded = false; RuntimeHelpers.PrepareConstrainedRegions(); try { if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.IncrementUndecidedEnlistments(); undecidedEnlistmentsIncremented = true; } } // This entire sequense needs to be executed before we can go on. lock ( enlistment ) { RuntimeHelpers.PrepareConstrainedRegions(); try { // Do the enlistment on the proxy. localResourceManagerShim = this.ResourceManagerShim; if ( null == localResourceManagerShim ) { // The TM must be down. Throw the appropriate exception. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx), null ); } if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) { // We need to create an EnlistmentNotifyShim if native threads are not allowed to enter managed code. handlePhase0 = HandleTable.AllocHandle( enlistment ); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist( handlePhase0, out phase0Shim ); phase0EnlistSucceeded = true; } enlistment.Phase0EnlistmentShim = phase0Shim; } enlistment.phase1Handle = HandleTable.AllocHandle( enlistment ); localResourceManagerShim.Enlist( oletxTransaction.RealTransaction.TransactionShim, enlistment.phase1Handle, out enlistmentShim ); enlistment.EnlistmentShim = enlistmentShim; } catch (COMException comException) { // There is no string mapping for XACT_E_TOOMANY_ENLISTMENTS, so we need to do it here. if ( NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == comException.ErrorCode ) { throw TransactionException.Create( SR.GetString( SR.TraceSourceOletx ), SR.GetString( SR.OletxTooManyEnlistments ), comException ); } OletxTransactionManager.ProxyException( comException ); throw; } finally { if ( enlistment.EnlistmentShim == null ) { // If the enlistment shim was never assigned then something blew up. // Perform some cleanup. if ( handlePhase0 != IntPtr.Zero && !phase0EnlistSucceeded ) { // Only clean up the phase0 handle if the phase 0 enlistment did not succeed. // This is because the notification processing code expects it to exist. HandleTable.FreeHandle( handlePhase0 ); } if ( enlistment.phase1Handle != IntPtr.Zero ) { HandleTable.FreeHandle( enlistment.phase1Handle ); } // Note this code used to call unenlist however this allows race conditions where // it is unclear if the handlePhase0 should be freed or not. The notification // thread should get a phase0Request and it will free the Handle at that point. } } } enlistmentSucceeded = true; } finally { if ( !enlistmentSucceeded && ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0) && undecidedEnlistmentsIncremented ) { oletxTransaction.RealTransaction.DecrementUndecidedEnlistments(); } } return enlistment; }
internal IPromotedEnlistment CommonEnlistVolatile( IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction ) { OletxVolatileEnlistment enlistment = null; bool needVoterEnlistment = false; bool needPhase0Enlistment = false; OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer = null; OletxPhase1VolatileEnlistmentContainer localPhase1VolatileContainer = null; IntPtr phase0Handle = IntPtr.Zero; IVoterBallotShim voterShim = null; IPhase0EnlistmentShim phase0Shim = null; bool enlistmentSucceeded = false; // Yes, we are talking to the proxy while holding the lock on the RealOletxTransaction. // If we don't then things get real sticky with other threads allocating containers. // We only do this the first time we get a depenent clone of a given type (delay vs. non-delay). // After that, we don't create a new container, except for Phase0 if we need to create one // for a second wave. RuntimeHelpers.PrepareConstrainedRegions(); try { lock ( this ) { enlistment = new OletxVolatileEnlistment( enlistmentNotification, enlistmentOptions, oletxTransaction ); if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) { if ( null == this.phase0EnlistVolatilementContainerList ) { // Not using a MemoryBarrier because all access to this member variable is done when holding // a lock on the object. this.phase0EnlistVolatilementContainerList = new ArrayList(1); } // We may have failed the proxy enlistment for the first container, but we would have // allocated the list. That is why we have this check here. if ( 0 == this.phase0EnlistVolatilementContainerList.Count ) { localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this ); needPhase0Enlistment = true; } else { localPhase0VolatileContainer = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer; if ( ! localPhase0VolatileContainer.NewEnlistmentsAllowed ) { localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this ); needPhase0Enlistment = true; } else { needPhase0Enlistment = false; } } if ( needPhase0Enlistment ) { // We need to create a VoterNotifyShim if native threads are not allowed to enter managed code. phase0Handle = HandleTable.AllocHandle( localPhase0VolatileContainer ); } } else // not EDPR = TRUE - may need a voter... { if ( null == this.phase1EnlistVolatilementContainer ) { needVoterEnlistment = true; localPhase1VolatileContainer = new OletxPhase1VolatileEnlistmentContainer( this ); // We need to create a VoterNotifyShim. localPhase1VolatileContainer.voterHandle = HandleTable.AllocHandle( localPhase1VolatileContainer ); } else { needVoterEnlistment = false; localPhase1VolatileContainer = this.phase1EnlistVolatilementContainer; } } try { // If enlistDuringPrepareRequired is true, we need to ask the proxy to create a Phase0 enlistment. if ( needPhase0Enlistment ) { lock ( localPhase0VolatileContainer ) { transactionShim.Phase0Enlist( phase0Handle, out phase0Shim ); localPhase0VolatileContainer.Phase0EnlistmentShim = phase0Shim; } } if ( needVoterEnlistment ) { this.transactionShim.CreateVoter( localPhase1VolatileContainer.voterHandle, out voterShim ); enlistmentSucceeded = true; localPhase1VolatileContainer.VoterBallotShim = voterShim; } if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) { localPhase0VolatileContainer.AddEnlistment( enlistment ); if ( needPhase0Enlistment ) { this.phase0EnlistVolatilementContainerList.Add( localPhase0VolatileContainer ); } } else { localPhase1VolatileContainer.AddEnlistment( enlistment ); if ( needVoterEnlistment ) { Debug.Assert( ( null == this.phase1EnlistVolatilementContainer ), "RealOletxTransaction.CommonEnlistVolatile - phase1VolContainer not null when expected." ); this.phase1EnlistVolatilementContainer = localPhase1VolatileContainer; } } } catch (COMException comException) { OletxTransactionManager.ProxyException( comException ); throw; } } } finally { if ( phase0Handle != IntPtr.Zero && localPhase0VolatileContainer.Phase0EnlistmentShim == null ) { HandleTable.FreeHandle( phase0Handle ); } if ( !enlistmentSucceeded && null != localPhase1VolatileContainer && localPhase1VolatileContainer.voterHandle != IntPtr.Zero && needVoterEnlistment ) { HandleTable.FreeHandle( localPhase1VolatileContainer.voterHandle ); } } return enlistment; }
internal static Transaction FindOrCreatePromotedTransaction(Guid transactionIdentifier, OletxTransaction oletx) { Transaction target = null; Hashtable promotedTransactionTable = PromotedTransactionTable; lock (promotedTransactionTable) { WeakReference reference = (WeakReference) promotedTransactionTable[transactionIdentifier]; if (reference != null) { target = reference.Target as Transaction; if (null != target) { oletx.Dispose(); return target.InternalClone(); } lock (promotedTransactionTable) { promotedTransactionTable.Remove(transactionIdentifier); } } target = new Transaction(oletx) { internalTransaction = { finalizedObject = new FinalizedObject(target.internalTransaction, oletx.Identifier) } }; reference = new WeakReference(target, false); promotedTransactionTable[oletx.Identifier] = reference; } oletx.savedLtmPromotedTransaction = target; FireDistributedTransactionStarted(target); return target; }