private void InvokeOutcomeFunction(TransactionStatus status) { WeakReference weakRealTransaction = null; lock (this) { if (this.haveIssuedOutcome) { return; } this.haveIssuedOutcome = true; this.savedStatus = status; weakRealTransaction = this.weakRealTransaction; } if (weakRealTransaction != null) { RealOletxTransaction target = weakRealTransaction.Target as RealOletxTransaction; if (target != null) { target.FireOutcome(status); if (target.phase0EnlistVolatilementContainerList != null) { foreach (OletxPhase0VolatileEnlistmentContainer container in target.phase0EnlistVolatilementContainerList) { container.OutcomeFromTransaction(status); } } if (((TransactionStatus.Aborted == status) || (TransactionStatus.InDoubt == status)) && (target.phase1EnlistVolatilementContainer != null)) { target.phase1EnlistVolatilementContainer.OutcomeFromTransaction(status); } } weakRealTransaction.Target = null; } }
internal void TMDown() { bool flag = true; RealOletxTransaction realTx = null; lock (this) { if (this.weakRealTransaction != null) { realTx = this.weakRealTransaction.Target as RealOletxTransaction; } } if (realTx != null) { lock (realTx) { flag = this.TransactionIsInDoubt(realTx); } } if (flag) { this.InDoubt(); } else { this.Aborted(); } }
internal bool TransactionIsInDoubt(RealOletxTransaction realTx) { if ((realTx.committableTransaction != null) && !realTx.committableTransaction.CommitCalled) { return(false); } return(realTx.UndecidedEnlistments == 0); }
internal OletxPhase1VolatileEnlistmentContainer(RealOletxTransaction realOletxTransaction) { base.realOletxTransaction = realOletxTransaction; base.phase = -1; base.outstandingNotifications = 0; base.incompleteDependentClones = 0; base.alreadyVoted = false; base.collectedVoteYes = true; base.enlistmentList = new ArrayList(); realOletxTransaction.IncrementUndecidedEnlistments(); }
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 OletxDependentTransaction(RealOletxTransaction realTransaction, bool delayCommit) : base(realTransaction) { if (realTransaction == null) { throw new ArgumentNullException("realTransaction"); } this.volatileEnlistmentContainer = base.realOletxTransaction.AddDependentClone(delayCommit); if (DiagnosticTrace.Information) { DependentCloneCreatedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.TransactionTraceId, delayCommit ? DependentCloneOption.BlockCommitUntilComplete : DependentCloneOption.RollbackIfNotComplete); } }
internal void SetRealTransaction(RealOletxTransaction realTx) { bool haveIssuedOutcome = false; TransactionStatus inDoubt = TransactionStatus.InDoubt; lock (this) { haveIssuedOutcome = this.haveIssuedOutcome; inDoubt = this.savedStatus; if (!haveIssuedOutcome) { this.weakRealTransaction = new WeakReference(realTx); this.txGuid = realTx.TxGuid; } } if (haveIssuedOutcome) { realTx.FireOutcome(inDoubt); if (((TransactionStatus.Aborted == inDoubt) || (TransactionStatus.InDoubt == inDoubt)) && (realTx.phase1EnlistVolatilementContainer != null)) { realTx.phase1EnlistVolatilementContainer.OutcomeFromTransaction(inDoubt); } } }
internal OletxPhase0VolatileEnlistmentContainer( RealOletxTransaction realOletxTransaction ) { Debug.Assert( null != realOletxTransaction, "Argument is null" ); // This will be set later, after the caller creates the enlistment with the proxy. this.phase0EnlistmentShim = null; this.realOletxTransaction = realOletxTransaction; this.phase = -1; this.aborting = false; this.tmWentDown = false; this.outstandingNotifications = 0; this.incompleteDependentClones = 0; this.alreadyVoted = false; // If anybody votes false, this will get set to false. this.collectedVoteYes = true; this.enlistmentList = new ArrayList(); // This is a new undecided enlistment on the transaction. Do this last since it has side affects. realOletxTransaction.IncrementUndecidedEnlistments(); }
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 bool TransactionIsInDoubt(RealOletxTransaction realTx) { if ((realTx.committableTransaction != null) && !realTx.committableTransaction.CommitCalled) { return false; } return (realTx.UndecidedEnlistments == 0); }
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; }
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; }
internal void SetRealTransaction( RealOletxTransaction realTx ) { bool localHaveIssuedOutcome = false; TransactionStatus localStatus = TransactionStatus.InDoubt; lock ( this ) { localHaveIssuedOutcome = this.haveIssuedOutcome; localStatus = this.savedStatus; // We want to do this while holding the lock. if ( ! localHaveIssuedOutcome ) { // We don't use MemoryBarrier here because all access to these member variables is done while holding // a lock on the object. // We are going to use a weak reference so the transaction object can get garbage // collected before we receive the outcome. this.weakRealTransaction = new WeakReference(realTx); // Save the transaction guid so that the transaction can be removed from the // TransactionTable this.txGuid = realTx.TxGuid; } } // We want to do this outside the lock because we are potentially calling out to user code. if ( localHaveIssuedOutcome ) { realTx.FireOutcome( localStatus ); // We may be getting this notification while there are still volatile prepare notifications outstanding. Tell the // container to drive the aborted notification in that case. if ( ( ( TransactionStatus.Aborted == localStatus ) || ( TransactionStatus.InDoubt == localStatus ) ) && ( null != realTx.phase1EnlistVolatilementContainer ) ) { realTx.phase1EnlistVolatilementContainer.OutcomeFromTransaction( localStatus ); } } }
// // We need to figure out if the transaction is InDoubt as a result of TMDown. This // can happen for a number of reasons. For instance we have responded prepared // to all of our enlistments or we have no enlistments. // internal bool TransactionIsInDoubt(RealOletxTransaction realTx) { if ( null != realTx.committableTransaction && !realTx.committableTransaction.CommitCalled ) { // If this is a committable transaction and commit has not been called // then we know the outcome. return false; } return realTx.UndecidedEnlistments == 0; }
/// <summary> /// Constructor for the Transaction object. Specifies the TransactionManager instance that is /// creating the transaction. /// </summary> /// <param name="transactionManager"> /// Specifies the TransactionManager instance that is creating the transaction. /// </param> internal OletxCommittableTransaction( RealOletxTransaction realOletxTransaction ) : base( realOletxTransaction ) { realOletxTransaction.committableTransaction = this; }
internal OletxTransaction(RealOletxTransaction realOletxTransaction) { this.realOletxTransaction = realOletxTransaction; // Tell the realOletxTransaction that we are here. this.realOletxTransaction.OletxTransactionCreated(); }
internal OletxTransaction(RealOletxTransaction realOletxTransaction) { this.traceIdentifier = TransactionTraceIdentifier.Empty; this.realOletxTransaction = realOletxTransaction; this.realOletxTransaction.OletxTransactionCreated(); }
/// <summary> /// Constructor for the Transaction object. Specifies the TransactionManager instance that is /// creating the transaction. /// </summary> /// <param name="transactionManager"> /// Specifies the TransactionManager instance that is creating the transaction. /// </param> internal OletxCommittableTransaction(RealOletxTransaction realOletxTransaction) : base(realOletxTransaction) { realOletxTransaction.committableTransaction = this; }
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; }
public void TMDown() { // Let's set ourselves up for reinitialization with the proxy by releasing our // reference to the resource manager shim, which will release its reference // to the proxy when it destructs. this.resourceManagerShim = null; // We need to look through all the transactions and tell them about // the TMDown so they can tell their Phase0VolatileEnlistmentContainers. Transaction tx = null; RealOletxTransaction realTx = null; IDictionaryEnumerator tableEnum = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxInternalResourceManager.TMDown" ); } // make a local copy of the hash table to avoid possible deadlocks when we lock both the global hash table // and the transaction object. Hashtable txHashTable = null; lock (TransactionManager.PromotedTransactionTable.SyncRoot) { txHashTable = (Hashtable)TransactionManager.PromotedTransactionTable.Clone(); } // No need to lock my hashtable, nobody is going to change it. tableEnum = txHashTable.GetEnumerator(); while (tableEnum.MoveNext()) { WeakReference txWeakRef = (WeakReference)tableEnum.Value; if (null != txWeakRef) { tx = (Transaction)txWeakRef.Target; if (null != tx) { realTx = tx.internalTransaction.PromotedTransaction.realOletxTransaction; // Only deal with transactions owned by my OletxTm. if (realTx.OletxTransactionManagerInstance == this.oletxTm) { realTx.TMDown(); } } } } // Now make a local copy of the hash table of resource managers and tell each of them. This is to // deal with Durable EDPR=true (phase0) enlistments. Each RM will also get a TMDown, but it will // come AFTER the "buggy" Phase0Request with abortHint=true - COMPlus Hashtable rmHashTable = null; if (null != OletxTransactionManager.resourceManagerHashTable) { OletxTransactionManager.resourceManagerHashTableLock.AcquireReaderLock(Timeout.Infinite); try { rmHashTable = (Hashtable)OletxTransactionManager.resourceManagerHashTable.Clone(); } finally { OletxTransactionManager.resourceManagerHashTableLock.ReleaseReaderLock(); } } if (null != rmHashTable) { // No need to lock my hashtable, nobody is going to change it. tableEnum = rmHashTable.GetEnumerator(); while (tableEnum.MoveNext()) { OletxResourceManager oletxRM = (OletxResourceManager)tableEnum.Value; if (null != oletxRM) { // When the RM spins through its enlistments, it will need to make sure that // the enlistment is for this particular TM. oletxRM.TMDownFromInternalRM(this.oletxTm); } } } // Now let's reinitialize the shim. this.oletxTm.dtcTransactionManagerLock.AcquireWriterLock(-1); try { this.oletxTm.ReinitializeProxy(); } finally { this.oletxTm.dtcTransactionManagerLock.ReleaseWriterLock(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxInternalResourceManager.TMDown" ); } }
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 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 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 void TMDown() { this.resourceManagerShim = null; Transaction target = null; RealOletxTransaction realOletxTransaction = null; IDictionaryEnumerator enumerator = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxInternalResourceManager.TMDown"); } Hashtable hashtable2 = null; lock (TransactionManager.PromotedTransactionTable.SyncRoot) { hashtable2 = (Hashtable)TransactionManager.PromotedTransactionTable.Clone(); } enumerator = hashtable2.GetEnumerator(); while (enumerator.MoveNext()) { WeakReference reference = (WeakReference)enumerator.Value; if (reference != null) { target = (Transaction)reference.Target; if (null != target) { realOletxTransaction = target.internalTransaction.PromotedTransaction.realOletxTransaction; if (realOletxTransaction.OletxTransactionManagerInstance == this.oletxTm) { realOletxTransaction.TMDown(); } } } } Hashtable hashtable = null; if (OletxTransactionManager.resourceManagerHashTable != null) { OletxTransactionManager.resourceManagerHashTableLock.AcquireReaderLock(-1); try { hashtable = (Hashtable)OletxTransactionManager.resourceManagerHashTable.Clone(); } finally { OletxTransactionManager.resourceManagerHashTableLock.ReleaseReaderLock(); } } if (hashtable != null) { enumerator = hashtable.GetEnumerator(); while (enumerator.MoveNext()) { OletxResourceManager manager = (OletxResourceManager)enumerator.Value; if (manager != null) { manager.TMDownFromInternalRM(this.oletxTm); } } } this.oletxTm.dtcTransactionManagerLock.AcquireWriterLock(-1); try { this.oletxTm.ReinitializeProxy(); } finally { this.oletxTm.dtcTransactionManagerLock.ReleaseWriterLock(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxInternalResourceManager.TMDown"); } }
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; }