public void Aborted(Exception e) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); etwLog.EnlistmentAborted(_internalEnlistment); } lock (_internalEnlistment.SyncRoot) { _internalEnlistment.State.Aborted(_internalEnlistment, e); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
public void ForceRollback() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); etwLog.EnlistmentForceRollback(_internalEnlistment); } lock (_internalEnlistment.SyncRoot) { _internalEnlistment.State.ForceRollback(_internalEnlistment, null); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
/// <summary> /// Create a promotable single phase enlistment that promotes to a distributed transaction manager other than MSDTC. /// </summary> /// <param name="promotableSinglePhaseNotification">The object that implements the IPromotableSinglePhaseNotification interface.</param> /// <param name="promoterType"> /// The promoter type Guid that identifies the format of the byte[] that is returned by the ITransactionPromoter.Promote /// call that is implemented by the IPromotableSinglePhaseNotificationObject, and thus the promoter of the transaction. /// </param> /// <returns> /// True if the enlistment is successful. /// /// False if the transaction already has a durable enlistment or promotable single phase enlistment or /// if the transaction has already promoted. In this case, the caller will need to enlist in the transaction through other /// means. /// /// If the Transaction.PromoterType matches the promoter type supported by the caller, then the /// Transaction.PromotedToken can be retrieved and used to enlist directly with the identified distributed transaction manager. /// /// How the enlistment is created with the distributed transaction manager identified by the Transaction.PromoterType /// is defined by that distributed transaction manager. /// </returns> public bool EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (Disposed) { throw new ObjectDisposedException(nameof(Transaction)); } ArgumentNullException.ThrowIfNull(promotableSinglePhaseNotification); if (promoterType == Guid.Empty) { throw new ArgumentException(SR.PromoterTypeInvalid, nameof(promoterType)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } bool succeeded = false; lock (_internalTransaction) { Debug.Assert(_internalTransaction.State != null); succeeded = _internalTransaction.State.EnlistPromotableSinglePhase(_internalTransaction, promotableSinglePhaseNotification, this, promoterType); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } return(succeeded); }
public void SetDistributedTransactionIdentifier(IPromotableSinglePhaseNotification promotableNotification, Guid distributedTransactionIdentifier) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (Disposed) { throw new ObjectDisposedException(nameof(Transaction)); } ArgumentNullException.ThrowIfNull(promotableNotification); if (distributedTransactionIdentifier == Guid.Empty) { throw new ArgumentException(null, nameof(distributedTransactionIdentifier)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } lock (_internalTransaction) { Debug.Assert(_internalTransaction.State != null); _internalTransaction.State.SetDistributedTransactionId(_internalTransaction, promotableNotification, distributedTransactionIdentifier); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } return; } }
// Forward request to the state machine to take the appropriate action. // public Enlistment EnlistVolatile(ISinglePhaseNotification singlePhaseNotification, EnlistmentOptions enlistmentOptions) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (Disposed) { throw new ObjectDisposedException(nameof(Transaction)); } if (singlePhaseNotification == null) { throw new ArgumentNullException(nameof(singlePhaseNotification)); } if (enlistmentOptions != EnlistmentOptions.None && enlistmentOptions != EnlistmentOptions.EnlistDuringPrepareRequired) { throw new ArgumentOutOfRangeException(nameof(enlistmentOptions)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } lock (_internalTransaction) { Enlistment enlistment = _internalTransaction.State.EnlistVolatile(_internalTransaction, singlePhaseNotification, enlistmentOptions, this); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } return(enlistment); } }
internal override void EnterState(InternalEnlistment enlistment) { // Set the enlistment state enlistment.State = this; Monitor.Exit(enlistment.Transaction); try // Don't hold this lock while calling into the application code. { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(enlistment, NotificationCall.Rollback); } enlistment.EnlistmentNotification.Rollback(enlistment.SinglePhaseEnlistment); } finally { Monitor.Enter(enlistment.Transaction); } }
public static IDtcTransaction GetDtcTransaction(Transaction transaction) { ArgumentNullException.ThrowIfNull(transaction); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetDtcTransaction"); } ConvertToOletxTransaction(transaction); IDtcTransaction transactionNative = OletxTransaction.GetDtcTransaction(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetDtcTransaction"); } return(transactionNative); }
public static byte[] GetTransmitterPropagationToken(Transaction transaction) { ArgumentNullException.ThrowIfNull(transaction); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransmitterPropagationToken"); } ConvertToOletxTransaction(transaction); byte[] token = OletxTransaction.GetTransmitterPropagationToken(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransmitterPropagationToken"); } return(token); }
internal static uint AdjustTimeout(TimeSpan timeout) { uint returnTimeout = 0; try { returnTimeout = Convert.ToUInt32(timeout.TotalMilliseconds, CultureInfo.CurrentCulture); } catch (OverflowException caughtEx) { // timeout.TotalMilliseconds might be negative, so let's catch overflow exceptions, just in case. TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.ExceptionConsumed(TraceSourceType.TraceSourceOleTx, caughtEx); } returnTimeout = uint.MaxValue; } return(returnTimeout); }
public void Complete() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } lock (_internalTransaction) { if (Disposed) { throw new ObjectDisposedException(nameof(DependentTransaction)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } _complete = true; Debug.Assert(_internalTransaction.State != null); if (_blocking) { _internalTransaction.State.CompleteBlockingClone(_internalTransaction); } else { _internalTransaction.State.CompleteAbortingClone(_internalTransaction); } } if (etwLog.IsEnabled()) { etwLog.TransactionDependentCloneComplete(this, "DependentTransaction"); etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
// Forward the commit to the state machine to take the appropriate action. // public void Commit() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); etwLog.TransactionCommit(this, "CommittableTransaction"); } ObjectDisposedException.ThrowIf(Disposed, this); lock (_internalTransaction) { if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } Debug.Assert(_internalTransaction.State != null); _internalTransaction.State.BeginCommit(_internalTransaction, false, null, null); // now that commit has started wait for the monitor on the transaction to know // if the transaction is done. do { if (_internalTransaction.State.IsCompleted(_internalTransaction)) { break; } } while (Monitor.Wait(_internalTransaction)); _internalTransaction.State.EndCommit(_internalTransaction); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
internal override void EnterState(InternalEnlistment enlistment) { // Set the enlistment state enlistment.State = this; Monitor.Exit(enlistment.Transaction); try // Don't hold this lock while calling into the application code. { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(enlistment, NotificationCall.InDoubt); } // Forward the notification to the enlistment enlistment.EnlistmentNotification.InDoubt(enlistment.PreparingEnlistment); } finally { Monitor.Enter(enlistment.Transaction); } }
internal override void EnterState(InternalEnlistment enlistment) { // Set the enlistment state enlistment.State = this; Monitor.Exit(enlistment.Transaction); try // Don't hold this lock while calling into the application code. { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(TraceSourceType.TraceSourceLtm, enlistment.EnlistmentTraceId, NotificationCall.Prepare); } Debug.Assert(enlistment.EnlistmentNotification != null); enlistment.EnlistmentNotification.Prepare(enlistment.PreparingEnlistment); } finally { Monitor.Enter(enlistment.Transaction); } }
internal void BeginCommit(InternalTransaction internalTransaction) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, this); etwLog.TransactionCommit(TraceSourceType.TraceSourceOleTx, TransactionTraceId, "CommittableTransaction"); } Debug.Assert(0 == Disposed, "OletxTransction object is disposed"); RealOletxTransaction.InternalTransaction = internalTransaction; _commitCalled = true; RealOletxTransaction.Commit(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, this, $"{nameof(OletxCommittableTransaction)}.{nameof(BeginCommit)}"); } }
public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative) { if (null == transactionNative) { throw new ArgumentNullException(nameof(transactionNative)); } TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceDistributed, "TransactionInterop.GetTransactionFromDtcTransaction"); } Transaction transaction = DistributedTransactionManager.GetTransactionFromDtcTransaction(transactionNative); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceDistributed, "TransactionInterop.GetTransactionFromDtcTransaction"); } return(transaction); }
public static void RecoveryComplete(Guid resourceManagerIdentifier) { if (resourceManagerIdentifier == Guid.Empty) { throw new ArgumentException(SR.BadResourceManagerId, nameof(resourceManagerIdentifier)); } TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, "TransactionManager.RecoveryComplete"); etwLog.TransactionManagerRecoveryComplete(resourceManagerIdentifier); } DistributedTransactionManager.ResourceManagerRecoveryComplete(resourceManagerIdentifier); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, "TransactionManager.RecoveryComplete"); } }
public void Rollback(Exception?e) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); etwLog.TransactionRollback(this, "Transaction"); } ObjectDisposedException.ThrowIf(Disposed, this); lock (_internalTransaction) { Debug.Assert(_internalTransaction.State != null); _internalTransaction.State.Rollback(_internalTransaction, e); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
public static byte[] GetTransmitterPropagationToken(Transaction transaction) { ArgumentNullException.ThrowIfNull(transaction); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransmitterPropagationToken)}"); } // First, make sure we are working with an OletxTransaction. OletxTransaction oletxTx = ConvertToOletxTransaction(transaction); byte[] token = GetTransmitterPropagationToken(oletxTx); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransmitterPropagationToken)}"); } return(token); }
// Create a dependent clone of the transaction that forwards requests to this object. // public DependentTransaction DependentClone( DependentCloneOption cloneOption ) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (cloneOption != DependentCloneOption.BlockCommitUntilComplete && cloneOption != DependentCloneOption.RollbackIfNotComplete) { throw new ArgumentOutOfRangeException(nameof(cloneOption)); } if (Disposed) { throw new ObjectDisposedException(nameof(Transaction)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } DependentTransaction clone = new DependentTransaction( _isoLevel, _internalTransaction, cloneOption == DependentCloneOption.BlockCommitUntilComplete); if (etwLog.IsEnabled()) { etwLog.TransactionCloneCreate(clone, "DependentTransaction"); etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } return(clone); }
// Ask the state machine for serialization info. // void ISerializable.GetObjectData( SerializationInfo serializationInfo, StreamingContext context) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (Disposed) { throw new ObjectDisposedException(nameof(Transaction)); } if (serializationInfo == null) { throw new ArgumentNullException(nameof(serializationInfo)); } if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } lock (_internalTransaction) { _internalTransaction.State.GetObjectData(_internalTransaction, serializationInfo, context); } if (etwLog.IsEnabled()) { etwLog.TransactionSerialized(this, "Transaction"); etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
internal override void InternalDispose() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } if (Interlocked.Exchange(ref _disposed, Transaction._disposedTrueValue) == Transaction._disposedTrueValue) { return; } Debug.Assert(_internalTransaction.State != null); if (_internalTransaction.State.get_Status(_internalTransaction) == TransactionStatus.Active) { lock (_internalTransaction) { // Since this is the root transaction do state based dispose. _internalTransaction.State.DisposeRoot(_internalTransaction); } } // Attempt to clean up the internal transaction long remainingITx = Interlocked.Decrement(ref _internalTransaction._cloneCount); if (remainingITx == 0) { _internalTransaction.Dispose(); } if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } }
internal override void EnterState(InternalEnlistment enlistment) { bool spcCommitted = false; // Set the enlistment state enlistment.State = this; Monitor.Exit(enlistment.Transaction); try { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(enlistment, NotificationCall.SinglePhaseCommit); } // Send the Commit notification to the enlistment if (enlistment.SinglePhaseNotification != null) { enlistment.SinglePhaseNotification.SinglePhaseCommit(enlistment.SinglePhaseEnlistment); } else { enlistment.PromotableSinglePhaseNotification.SinglePhaseCommit(enlistment.SinglePhaseEnlistment); } spcCommitted = true; } finally { if (!spcCommitted) { enlistment.SinglePhaseEnlistment.InDoubt(); } Monitor.Enter(enlistment.Transaction); } }
public void Complete() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, this); } if (_disposed) { throw new ObjectDisposedException(nameof(TransactionScope)); } if (_complete) { throw TransactionException.CreateInvalidOperationException(TraceSourceType.TraceSourceBase, SR.DisposeScope, null); } _complete = true; if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, this); } }
private void Initialize( Transaction transactionToUse, TimeSpan scopeTimeout, bool interopModeSpecified) { if (null == transactionToUse) { throw new ArgumentNullException(nameof(transactionToUse)); } ValidateScopeTimeout(nameof(scopeTimeout), scopeTimeout); CommonInitialize(); if (TimeSpan.Zero != scopeTimeout) { _scopeTimer = new Timer( TimerCallback, this, scopeTimeout, TimeSpan.Zero ); } _expectedCurrent = transactionToUse; _interopModeSpecified = interopModeSpecified; TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.TransactionScopeCreated(_expectedCurrent.TransactionTraceId, TransactionScopeResult.TransactionPassed); } PushScope(); }
public TransactionScope( Transaction transactionToUse, TimeSpan scopeTimeout, TransactionScopeAsyncFlowOption asyncFlowOption) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, this); } ValidateAndSetAsyncFlowOption(asyncFlowOption); Initialize( transactionToUse, scopeTimeout, false); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, this); } }
// Create a clone of the transaction that forwards requests to this object. // public Transaction Clone() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } ObjectDisposedException.ThrowIf(Disposed, this); if (_complete) { throw TransactionException.CreateTransactionCompletedException(DistributedTxId); } Transaction clone = InternalClone(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } return(clone); }
public byte[] RecoveryInformation() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceLtm, this); } try { lock (_internalEnlistment.SyncRoot) { return(_internalEnlistment.State.RecoveryInformation(_internalEnlistment)); } } finally { if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceLtm, this); } } }
public static IDtcTransaction GetDtcTransaction(Transaction transaction) { if (null == transaction) { throw new ArgumentNullException(nameof(transaction)); } TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceDistributed, "TransactionInterop.GetDtcTransaction"); } DistributedTransaction dTx = ConvertToDistributedTransaction(transaction); IDtcTransaction transactionNative = dTx.GetDtcTransaction(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceDistributed, "TransactionInterop.GetDtcTransaction"); } return(transactionNative); }
public static Transaction GetTransactionFromExportCookie(byte[] cookie) { ArgumentNullException.ThrowIfNull(cookie); if (cookie.Length < 32) { throw new ArgumentException(SR.InvalidArgument, nameof(cookie)); } TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromExportCookie)}"); } var cookieCopy = new byte[cookie.Length]; Buffer.BlockCopy(cookie, 0, cookieCopy, 0, cookie.Length); cookie = cookieCopy; Transaction? transaction; TransactionShim?transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment?outcomeEnlistment; OletxTransaction? oleTx; // Extract the transaction guid from the propagation token to see if we already have a // transaction object for the transaction. // In a cookie, the transaction guid is preceded by a signature guid. var txId = new Guid(cookie.AsSpan(16, 16)); // 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 (transaction != null) { if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.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(); oletxTm.DtcTransactionManager.ProxyShimFactory.Import(cookie, outcomeEnlistment, out txIdentifier, out oletxIsoLevel, out transactionShim); } 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.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 (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromExportCookie)}"); } return(transaction); }
public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative) { ArgumentNullException.ThrowIfNull(transactionNative, nameof(transactionNative)); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}"); } Transaction? transaction = null; bool tooLate = false; TransactionShim?transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment? outcomeEnlistment = null; RealOletxTransaction?realTx = null; OletxTransaction? oleTx = null; // Let's get the guid of the transaction from the proxy to see if we already have an object. if (transactionNative is not ITransaction myTransactionNative) { throw new ArgumentException(SR.InvalidArgument, nameof(transactionNative)); } OletxXactTransInfo xactInfo; try { myTransactionNative.GetTransactionInfo(out xactInfo); } catch (COMException ex) when(ex.ErrorCode == OletxHelper.XACT_E_NOTRANSACTION) { // 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 (transaction != null) { if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}"); } return(transaction); } // We need to create a new RealOletxTransaction... oletxTm.DtcTransactionManagerLock.AcquireReaderLock(-1); try { outcomeEnlistment = new OutcomeEnlistment(); oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim( transactionNative, outcomeEnlistment, out txIdentifier, out oletxIsoLevel, out transactionShim); } 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 (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}"); } return(transaction); }