protected override void Execute(NativeActivityContext context) { //Gets the ambient RuntimeTransactionHandle which allows access to the runtime transaction RuntimeTransactionHandle rth = context.Properties.Find(typeof(RuntimeTransactionHandle).FullName) as RuntimeTransactionHandle; if (rth == null) { throw new InvalidOperationException("There is no RuntimeTransactionHandle"); } //The runtime transaction Transaction t = rth.GetCurrentTransaction(context); if (t == null) { throw new InvalidOperationException("There is no transaction to rollback"); } Exception e = Reason.Get(context); if (e == null) { e = new TransactionException("The Rollback activity was used to rollback the transaction"); } t.Rollback(e); }
internal virtual void Aborted(InternalEnlistment enlistment, Exception e) { throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
internal virtual void ChangeStateSinglePhaseCommit(InternalEnlistment enlistment) { Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", this.GetType())); throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
internal override void Rollback(InternalTransaction tx, Exception e) { throw TransactionException.CreateTransactionStateException(System.Transactions.SR.GetString("TraceSourceLtm"), tx.innerException); }
public static void ThrowTransactionProxyException(int hr, TransactionException exception) { throw new TransactionProxyException(hr, exception); }
private void MapTxExceptionToHR(TransactionException txException, bool isInCommit) { TransactionAbortedException exception = txException as TransactionAbortedException; if (exception != null) { if (isInCommit) { TransactionProxyException.ThrowTransactionProxyException(-2147164158, exception); } else { TransactionProxyException.ThrowTransactionProxyException(-2147164157, exception); } } TransactionManagerCommunicationException exception2 = txException as TransactionManagerCommunicationException; if (exception2 != null) { TransactionProxyException.ThrowTransactionProxyException(-2147164145, exception2); } COMException baseException = txException.GetBaseException() as COMException; if (baseException != null) { TransactionProxyException.ThrowTransactionProxyException(baseException.ErrorCode, txException); } else { TransactionProxyException.ThrowTransactionProxyException(-2147418113, txException); } }
internal virtual byte[] RecoveryInformation(InternalEnlistment enlistment) { throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
// Process a timer event private void ThreadTimer(object state) { // // Theory of operation. // // To timeout transactions we must walk down the list starting from the head // until we find a link with an absolute timeout that is greater than our own. // At that point everything further down in the list is elegable to be timed // out. So simply remove that link in the list and walk down from that point // timing out any transaction that is found. // // There could be a race between this callback being queued and the timer // being disabled. If we get here when the timer is disabled, just return. if (!_timerEnabled) { return; } // Increment the number of ticks _ticks++; _lastTimerTime = DateTime.UtcNow.Ticks; // // First find the starting point of transactions that should time out. Every transaction after // that point will timeout so once we've found it then it is just a matter of traversing the // structure. // BucketSet lastBucketSet = null; BucketSet currentBucketSet = _headBucketSet; // The list always has a head. // Acquire a writer lock before checking to see if we should disable the timer. // Adding of transactions acquires a reader lock and might insert a new BucketSet. // If that races with our check for a BucketSet existing, we may not timeout that // transaction that is being added. WeakReference nextWeakSet = null; BucketSet nextBucketSet = null; nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak; if (nextWeakSet != null) { nextBucketSet = (BucketSet)nextWeakSet.Target; } if (nextBucketSet == null) { _rwLock.EnterWriteLock(); try { // Access the nextBucketSet again in writer lock to account for any race before disabling the timeout. nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak; if (nextWeakSet != null) { nextBucketSet = (BucketSet)nextWeakSet.Target; } if (nextBucketSet == null) { // // Special case to allow for disabling the timer. // // If there are no transactions on the timeout list we can disable the // timer. if (!_timer.Change(Timeout.Infinite, Timeout.Infinite)) { throw TransactionException.CreateInvalidOperationException( TraceSourceType.TraceSourceLtm, SR.UnexpectedTimerFailure, null ); } _timerEnabled = false; return; } } finally { _rwLock.ExitWriteLock(); } } // Note it is slightly subtle that we always skip the head node. This is done // on purpose because the head node contains transactions with essentially // an infinite timeout. do { do { nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak; if (nextWeakSet == null) { // Nothing more to do. return; } nextBucketSet = (BucketSet)nextWeakSet.Target; if (nextBucketSet == null) { // Again nothing more to do. return; } lastBucketSet = currentBucketSet; currentBucketSet = nextBucketSet; }while (currentBucketSet.AbsoluteTimeout > _ticks); // // Pinch off the list at this point making sure it is still the correct set. // // Note: We may lose a race with an "Add" thread that is inserting a BucketSet in this location in // the list. If that happens, this CompareExchange will not be performed and the returned abortingSetsWeak // value will NOT equal nextWeakSet. But we check for that and if this condition occurs, this iteration of // the timer thread will simply return, not timing out any transactions. When the next timer interval // expires, the thread will walk the list again, find the appropriate BucketSet to pinch off, and // then time out the transactions. This means that it is possible for a transaction to live a bit longer, // but not much. WeakReference abortingSetsWeak = (WeakReference)Interlocked.CompareExchange(ref lastBucketSet.nextSetWeak, null, nextWeakSet); if (abortingSetsWeak == nextWeakSet) { // Yea - now proceed to abort the transactions. BucketSet abortingBucketSets = null; do { if (abortingSetsWeak != null) { abortingBucketSets = (BucketSet)abortingSetsWeak.Target; } else { abortingBucketSets = null; } if (abortingBucketSets != null) { abortingBucketSets.TimeoutTransactions(); abortingSetsWeak = (WeakReference)abortingBucketSets.nextSetWeak; } }while (abortingBucketSets != null); // That's all we needed to do. break; } // We missed pulling the right transactions off. Loop back up and try again. currentBucketSet = lastBucketSet; }while (true); }
internal virtual void InDoubt(InternalEnlistment enlistment, Exception e) { throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null); }
internal virtual void Committed(InternalEnlistment enlistment) { throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null); }
internal virtual void ChangeStatePreparing(InternalEnlistment enlistment) { Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", this.GetType())); throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null); }
public void OnTransactionAbortOrInDoubt(TransactionException exception) { this.AbortInstance(exception, false); }
internal virtual void InternalAborted(InternalEnlistment enlistment) { Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType())); throw TransactionException.CreateEnlistmentStateException(SR.TraceSourceLtm, null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
internal virtual void Committed(InternalEnlistment enlistment) { throw TransactionException.CreateEnlistmentStateException(SR.TraceSourceLtm, null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
internal virtual void ForceRollback(InternalEnlistment enlistment, Exception?e) { throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
internal virtual byte[] RecoveryInformation(InternalEnlistment enlistment) { throw TransactionException.CreateEnlistmentStateException(SR.GetString(SR.TraceSourceLtm), null); }
internal virtual void ChangeStateSinglePhaseCommit(InternalEnlistment enlistment) { Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}"); throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
// We don't have a finalizer (~TransactionScope) because all it would be able to do is try to // operate on other managed objects (the transaction), which is not safe to do because they may // already have been finalized. public void Dispose() { bool successful = false; TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, this); } if (_disposed) { if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, this); } return; } // Dispose for a scope can only be called on the thread where the scope was created. if ((_scopeThread != Thread.CurrentThread) && !AsyncFlowEnabled) { if (etwLog.IsEnabled()) { etwLog.InvalidOperation("TransactionScope", "InvalidScopeThread"); } throw new InvalidOperationException(SR.InvalidScopeThread); } Exception?exToThrow = null; try { // Single threaded from this point _disposed = true; Debug.Assert(_threadContextData != null); // First, lets pop the "stack" of TransactionScopes and dispose each one that is above us in // the stack, making sure they are NOT consistent before disposing them. // Optimize the first lookup by getting both the actual current scope and actual current // transaction at the same time. TransactionScope?actualCurrentScope = _threadContextData.CurrentScope; Transaction? contextTransaction = null; Transaction? current = Transaction.FastGetTransaction(actualCurrentScope, _threadContextData, out contextTransaction); if (!Equals(actualCurrentScope)) { // Ok this is bad. But just how bad is it. The worst case scenario is that someone is // poping scopes out of order and has placed a new transaction in the top level scope. // Check for that now. if (actualCurrentScope == null) { // Something must have gone wrong trying to clean up a bad scope // stack previously. // Make a best effort to abort the active transaction. Transaction?rollbackTransaction = _committableTransaction; if (rollbackTransaction == null) { rollbackTransaction = _dependentTransaction; } Debug.Assert(rollbackTransaction != null); rollbackTransaction.Rollback(); successful = true; throw TransactionException.CreateInvalidOperationException( TraceSourceType.TraceSourceBase, SR.TransactionScopeInvalidNesting, null, rollbackTransaction.DistributedTxId); } // Verify that expectedCurrent is the same as the "current" current if we the interopOption value is None. else if (EnterpriseServicesInteropOption.None == actualCurrentScope._interopOption) { if (((null != actualCurrentScope._expectedCurrent) && (!actualCurrentScope._expectedCurrent.Equals(current))) || ((null != current) && (null == actualCurrentScope._expectedCurrent)) ) { TransactionTraceIdentifier myId; TransactionTraceIdentifier currentId; if (null == current) { currentId = TransactionTraceIdentifier.Empty; } else { currentId = current.TransactionTraceId; } if (null == _expectedCurrent) { myId = TransactionTraceIdentifier.Empty; } else { myId = _expectedCurrent.TransactionTraceId; } if (etwLog.IsEnabled()) { etwLog.TransactionScopeCurrentChanged(currentId, myId); } exToThrow = TransactionException.CreateInvalidOperationException(TraceSourceType.TraceSourceBase, SR.TransactionScopeIncorrectCurrent, null, current == null ? Guid.Empty : current.DistributedTxId); // If there is a current transaction, abort it. if (null != current) { try { current.Rollback(); } catch (TransactionException) { // we are already going to throw and exception, so just ignore this one. } catch (ObjectDisposedException) { // Dito } } } } // Now fix up the scopes while (!Equals(actualCurrentScope)) { if (null == exToThrow) { exToThrow = TransactionException.CreateInvalidOperationException(TraceSourceType.TraceSourceBase, SR.TransactionScopeInvalidNesting, null, current == null ? Guid.Empty : current.DistributedTxId); } if (null == actualCurrentScope !._expectedCurrent) { if (etwLog.IsEnabled()) { etwLog.TransactionScopeNestedIncorrectly(TransactionTraceIdentifier.Empty); } } else { if (etwLog.IsEnabled()) { etwLog.TransactionScopeNestedIncorrectly(actualCurrentScope._expectedCurrent.TransactionTraceId); } } actualCurrentScope._complete = false; try { actualCurrentScope.InternalDispose(); } catch (TransactionException) { // we are already going to throw an exception, so just ignore this one. } actualCurrentScope = _threadContextData.CurrentScope; // We want to fail this scope, too, because work may have been done in one of these other // nested scopes that really should have been done in my scope. _complete = false; } }
internal virtual void InDoubt(InternalEnlistment enlistment, Exception e) { throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
// Override of get_RecoveryInformation to be more specific with the exception string. internal override byte[] RecoveryInformation(InternalEnlistment enlistment) { throw TransactionException.CreateInvalidOperationException(TraceSourceType.TraceSourceLtm, SR.VolEnlistNoRecoveryInfo, null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
private void MapTxExceptionToHR(TransactionException txException) { this.MapTxExceptionToHR(txException, false); }
internal virtual void ChangeStatePreparing(InternalEnlistment enlistment) { Debug.Assert(false, string.Format(null, "Invalid Event for InternalEnlistment State; Current State: {0}", GetType())); throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); }
private TransactionProxyException(int hr, TransactionException exception) : base(null, exception) { base.HResult = hr; }
internal override void BeginCommit(InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState) { throw TransactionException.CreateTransactionStateException(System.Transactions.SR.GetString("TraceSourceLtm"), tx.innerException); }
public void OnTransactionAbortOrInDoubt(TransactionException exception) { Fx.Assert(exception != null, "Need a valid TransactionException to call this"); this.AbortInstance(exception, false); }
internal override void CreateBlockingClone(InternalTransaction tx) { throw TransactionException.CreateTransactionStateException(System.Transactions.SR.GetString("TraceSourceLtm"), tx.innerException); }