internal OletxEnlistment( bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, Guid transactionGuid, EnlistmentOptions enlistmentOptions, OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction) : base(oletxResourceManager, oletxTransaction) { // This will get set later by the creator of this object after it // has enlisted with the proxy. EnlistmentShim = null; _phase0Shim = null; _canDoSinglePhase = canDoSinglePhase; _iEnlistmentNotification = enlistmentNotification; State = OletxEnlistmentState.Active; _transactionGuid = transactionGuid; _proxyPrepareInfoByteArray = null; TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.EnlistmentCreated(TraceSourceType.TraceSourceOleTx, InternalTraceIdentifier, EnlistmentType.Durable, enlistmentOptions); } // Always do this last in case anything earlier fails. AddToEnlistmentTable(); }
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 void Prepare(OletxVolatileEnlistmentContainer container) { OletxVolatileEnlistmentState active = OletxVolatileEnlistmentState.Active; IEnlistmentNotificationInternal iEnlistmentNotification = null; lock (this) { iEnlistmentNotification = this.iEnlistmentNotification; if (this.state == OletxVolatileEnlistmentState.Active) { active = this.state = OletxVolatileEnlistmentState.Preparing; } else { active = this.state; } this.container = container; } if (OletxVolatileEnlistmentState.Preparing == active) { if (iEnlistmentNotification != null) { if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Prepare); } iEnlistmentNotification.Prepare(this); return; } if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } if (OletxVolatileEnlistmentState.Done == active) { container.DecrementOutstandingNotifications(true); } else if ((OletxVolatileEnlistmentState.Prepared == active) && this.enlistDuringPrepareRequired) { container.DecrementOutstandingNotifications(true); } else if ((OletxVolatileEnlistmentState.Aborting == active) || (OletxVolatileEnlistmentState.Aborted == active)) { container.DecrementOutstandingNotifications(false); } else { if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } }
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); } }
public void CommitRequest() { IEnlistmentShim enlistmentShim = null; IEnlistmentNotificationInternal iEnlistmentNotification = null; bool flag = false; lock (this) { if (OletxEnlistmentState.Prepared == this.state) { this.state = OletxEnlistmentState.Committing; iEnlistmentNotification = this.iEnlistmentNotification; } else { enlistmentShim = this.EnlistmentShim; flag = true; } } if (iEnlistmentNotification != null) { if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Commit); } iEnlistmentNotification.Commit(this); } else if (enlistmentShim != null) { try { enlistmentShim.CommitRequestDone(); } catch (COMException exception) { if ((System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN != exception.ErrorCode) && (System.Transactions.Oletx.NativeMethods.XACT_E_TMNOTAVAILABLE != exception.ErrorCode)) { throw; } flag = true; if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } finally { if (flag) { this.FinishEnlistment(); } } } }
internal void FinishEnlistment() { lock (this) { if (this.enlistmentShim == null) { base.oletxResourceManager.RemoveFromReenlistPending(this); } this.iEnlistmentNotification = null; base.RemoveFromEnlistmentTable(); } }
internal void InDoubt() { OletxVolatileEnlistmentState active = OletxVolatileEnlistmentState.Active; IEnlistmentNotificationInternal iEnlistmentNotification = null; lock (this) { if (OletxVolatileEnlistmentState.Prepared == this.state) { active = this.state = OletxVolatileEnlistmentState.InDoubt; iEnlistmentNotification = this.iEnlistmentNotification; } else { if (OletxVolatileEnlistmentState.Preparing == this.state) { this.pendingOutcome = TransactionStatus.InDoubt; } active = this.state; } } if (OletxVolatileEnlistmentState.InDoubt == active) { if (iEnlistmentNotification != null) { if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.InDoubt); } iEnlistmentNotification.InDoubt(this); return; } if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } if ((OletxVolatileEnlistmentState.Preparing != active) && (OletxVolatileEnlistmentState.Done != active)) { if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } }
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(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions) { if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransaction.EnlistVolatile( IEnlistmentNotificationInternal )"); } if ((this.realOletxTransaction == null) || this.realOletxTransaction.TooLateForEnlistments) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("TooLate"), null); } IPromotedEnlistment enlistment = this.realOletxTransaction.EnlistVolatile(enlistmentNotification, enlistmentOptions, this); if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransaction.EnlistVolatile( IEnlistmentNotificationInternal )"); } return(enlistment); }
internal OletxEnlistment ReenlistTransaction( Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotificationInternal enlistmentNotification ) { if (null == recoveryInformation) { throw new ArgumentNullException("recoveryInformation"); } if (null == enlistmentNotification) { throw new ArgumentNullException("enlistmentNotification"); } // Now go find the resource manager in the collection. OletxResourceManager oletxResourceManager = RegisterResourceManager(resourceManagerIdentifier); if (null == oletxResourceManager) { throw new ArgumentException(SR.GetString(SR.InvalidArgument), "resourceManagerIdentifier"); } if (oletxResourceManager.RecoveryCompleteCalledByApplication) { throw new InvalidOperationException(SR.GetString(SR.ReenlistAfterRecoveryComplete)); } // Now ask the resource manager to reenlist. OletxEnlistment returnValue = oletxResourceManager.Reenlist( recoveryInformation.Length, recoveryInformation, enlistmentNotification ); return(returnValue); }
internal OletxEnlistment(IEnlistmentNotificationInternal enlistmentNotification, OletxTransactionStatus xactStatus, byte[] prepareInfoByteArray, OletxResourceManager oletxResourceManager) : base(oletxResourceManager, null) { this.transactionGuid = Guid.Empty; this.phase1Handle = IntPtr.Zero; this.enlistmentShim = null; this.phase0Shim = null; this.canDoSinglePhase = false; this.iEnlistmentNotification = enlistmentNotification; this.state = OletxEnlistmentState.Active; int length = prepareInfoByteArray.Length; this.proxyPrepareInfoByteArray = new byte[length]; Array.Copy(prepareInfoByteArray, this.proxyPrepareInfoByteArray, length); byte[] destinationArray = new byte[0x10]; Array.Copy(this.proxyPrepareInfoByteArray, destinationArray, 0x10); this.transactionGuid = new Guid(destinationArray); base.transactionGuidString = this.transactionGuid.ToString(); switch (xactStatus) { case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED: this.state = OletxEnlistmentState.Prepared; lock (oletxResourceManager.reenlistList) { oletxResourceManager.reenlistList.Add(this); oletxResourceManager.StartReenlistThread(); goto Label_01CD; } break; case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED: this.state = OletxEnlistmentState.Aborting; if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Rollback); } this.iEnlistmentNotification.Rollback(this); goto Label_01CD; case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED: this.state = OletxEnlistmentState.Committing; lock (oletxResourceManager.reenlistList) { oletxResourceManager.reenlistPendingList.Add(this); } if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Commit); } this.iEnlistmentNotification.Commit(this); goto Label_01CD; } if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxEnlistmentUnexpectedTransactionStatus")); } throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxEnlistmentUnexpectedTransactionStatus"), null); Label_01CD: if (DiagnosticTrace.Information) { EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Durable, EnlistmentOptions.None); } base.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 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 void FinishEnlistment() { lock ( this ) { // If we don't have a wrappedTransactionEnlistmentAsync, we may // need to remove ourselves from the reenlistPendingList in the // resource manager. if ( null == this.enlistmentShim ) { oletxResourceManager.RemoveFromReenlistPending( this ); } this.iEnlistmentNotification = null; RemoveFromEnlistmentTable(); } }
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 bool PrepareRequest(bool singlePhase, byte[] prepareInfo) { IEnlistmentShim enlistmentShim = null; OletxEnlistmentState active = OletxEnlistmentState.Active; IEnlistmentNotificationInternal iEnlistmentNotification = null; OletxRecoveryInformation thingToConvert = null; lock (this) { if (this.state == OletxEnlistmentState.Active) { active = this.state = OletxEnlistmentState.Preparing; } else { active = this.state; } iEnlistmentNotification = this.iEnlistmentNotification; enlistmentShim = this.EnlistmentShim; base.oletxTransaction.realOletxTransaction.TooLateForEnlistments = true; } if (OletxEnlistmentState.Preparing == active) { thingToConvert = new OletxRecoveryInformation(prepareInfo); this.isSinglePhase = singlePhase; long length = prepareInfo.Length; this.proxyPrepareInfoByteArray = new byte[length]; Array.Copy(prepareInfo, this.proxyPrepareInfoByteArray, length); if (this.isSinglePhase && this.canDoSinglePhase) { ISinglePhaseNotificationInternal internal3 = (ISinglePhaseNotificationInternal)iEnlistmentNotification; this.state = OletxEnlistmentState.SinglePhaseCommitting; if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.SinglePhaseCommit); } internal3.SinglePhaseCommit(this); return(true); } byte[] resourceManagerRecoveryInformation = TransactionManager.ConvertToByteArray(thingToConvert); this.state = OletxEnlistmentState.Preparing; this.prepareInfoByteArray = TransactionManager.GetRecoveryInformation(base.oletxResourceManager.oletxTransactionManager.CreationNodeName, resourceManagerRecoveryInformation); if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Prepare); } iEnlistmentNotification.Prepare(this); return(false); } if (OletxEnlistmentState.Prepared == active) { try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.Prepared); return(false); } catch (COMException exception3) { OletxTransactionManager.ProxyException(exception3); throw; } } if (OletxEnlistmentState.Done == active) { try { bool flag; try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.ReadOnly); flag = true; } finally { this.FinishEnlistment(); } return(flag); } catch (COMException exception2) { OletxTransactionManager.ProxyException(exception2); throw; } } try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.Failed); } catch (COMException exception) { if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } return(true); }
internal IPromotedEnlistment EnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { return this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction); }
internal OletxEnlistment ReenlistTransaction( Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotificationInternal enlistmentNotification ) { if ( null == recoveryInformation ) { throw new ArgumentNullException( "recoveryInformation" ); } if ( null == enlistmentNotification ) { throw new ArgumentNullException( "enlistmentNotification" ); } // Now go find the resource manager in the collection. OletxResourceManager oletxResourceManager = RegisterResourceManager( resourceManagerIdentifier ); if ( null == oletxResourceManager ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "resourceManagerIdentifier" ); } if ( oletxResourceManager.RecoveryCompleteCalledByApplication ) { throw new InvalidOperationException( SR.GetString( SR.ReenlistAfterRecoveryComplete )); } // Now ask the resource manager to reenlist. OletxEnlistment returnValue = oletxResourceManager.Reenlist( recoveryInformation.Length, recoveryInformation, enlistmentNotification ); return returnValue; }
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 OletxEnlistment( IEnlistmentNotificationInternal enlistmentNotification, OletxTransactionStatus xactStatus, byte[] prepareInfoByteArray, OletxResourceManager oletxResourceManager) : base(oletxResourceManager, null) { // This will get set later by the creator of this object after it // has enlisted with the proxy. EnlistmentShim = null; _phase0Shim = null; _canDoSinglePhase = false; _iEnlistmentNotification = enlistmentNotification; State = OletxEnlistmentState.Active; // Do this before we do any tracing because it will affect the trace identifiers that we generate. Debug.Assert(prepareInfoByteArray != null, "OletxEnlistment.ctor - null oletxTransaction without a prepareInfoByteArray"); int prepareInfoLength = prepareInfoByteArray.Length; _proxyPrepareInfoByteArray = new byte[prepareInfoLength]; Array.Copy(prepareInfoByteArray, _proxyPrepareInfoByteArray, prepareInfoLength); byte[] txGuidByteArray = new byte[16]; Array.Copy(_proxyPrepareInfoByteArray, txGuidByteArray, 16); _transactionGuid = new Guid(txGuidByteArray); TransactionGuidString = _transactionGuid.ToString(); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; // If this is being created as part of a Reenlist and we already know the // outcome, then tell the application. switch (xactStatus) { case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED: { State = OletxEnlistmentState.Aborting; if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(TraceSourceType.TraceSourceOleTx, InternalTraceIdentifier, NotificationCall.Rollback); } _iEnlistmentNotification.Rollback(this); break; } case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED: { State = OletxEnlistmentState.Committing; // We are going to send the notification to the RM. We need to put the // enlistment on the reenlistPendingList. We lock the reenlistList because // we have decided that is the lock that protects both lists. The entry will // be taken off the reenlistPendingList when the enlistment has // EnlistmentDone called on it. The enlistment will call // RemoveFromReenlistPending. lock (oletxResourceManager.ReenlistList) { oletxResourceManager.ReenlistPendingList.Add(this); } if (etwLog.IsEnabled()) { etwLog.EnlistmentStatus(TraceSourceType.TraceSourceOleTx, InternalTraceIdentifier, NotificationCall.Commit); } _iEnlistmentNotification.Commit(this); break; } case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED: { State = OletxEnlistmentState.Prepared; lock (oletxResourceManager.ReenlistList) { oletxResourceManager.ReenlistList.Add(this); oletxResourceManager.StartReenlistThread(); } break; } default: { if (etwLog.IsEnabled()) { etwLog.InternalError(SR.OletxEnlistmentUnexpectedTransactionStatus); } throw TransactionException.Create( SR.OletxEnlistmentUnexpectedTransactionStatus, null, DistributedTxId); } } if (etwLog.IsEnabled()) { etwLog.EnlistmentCreated(TraceSourceType.TraceSourceOleTx, InternalTraceIdentifier, EnlistmentType.Durable, EnlistmentOptions.None); } // Always do this last in case anything prior to this fails. AddToEnlistmentTable(); }
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 OletxEnlistment Reenlist( int prepareInfoLength, byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification ) { OletxTransactionOutcome outcome = OletxTransactionOutcome.NotKnownYet; OletxTransactionStatus xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE; // Put the recovery information into a stream. MemoryStream stream = new MemoryStream( prepareInfo ); // First extract the OletxRecoveryInformation from the stream. IFormatter formatter = new BinaryFormatter(); OletxRecoveryInformation oletxRecoveryInformation; try { oletxRecoveryInformation = formatter.Deserialize( stream ) as OletxRecoveryInformation; } catch (SerializationException se) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "prepareInfo", se ); } if ( null == oletxRecoveryInformation ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "prepareInfo" ); } // Verify that the resource manager guid in the recovery info matches that of the calling resource manager. byte[] rmGuidArray = new byte[16]; for ( int i = 0; i < 16; i++ ) { rmGuidArray[i] = oletxRecoveryInformation.proxyRecoveryInformation[i + 16]; } Guid rmGuid = new Guid( rmGuidArray ); if ( rmGuid != this.resourceManagerIdentifier ) { throw TransactionException.Create( SR.GetString( SR.TraceSourceOletx ), SR.GetString( SR.ResourceManagerIdDoesNotMatchRecoveryInformation ), null ); } // Ask the proxy resource manager to reenlist. IResourceManagerShim localResourceManagerShim = null; try { localResourceManagerShim = this.ResourceManagerShim; if ( null == localResourceManagerShim ) { // The TM must be down. Throw the exception that will get caught below and will cause // the enlistment to start the ReenlistThread. The TMDown thread will be trying to reestablish // connection with the TM and will start the reenlist thread when it does. throw new COMException( SR.GetString( SR.DtcTransactionManagerUnavailable ), NativeMethods.XACT_E_CONNECTION_DOWN ); } // Only wait for 5 milliseconds. If the TM doesn't have the outcome now, we will // put the enlistment on the reenlistList for later processing. localResourceManagerShim.Reenlist( Convert.ToUInt32( oletxRecoveryInformation.proxyRecoveryInformation.Length, CultureInfo.InvariantCulture ), oletxRecoveryInformation.proxyRecoveryInformation, out outcome ); if ( OletxTransactionOutcome.Committed == outcome ) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED; } else if ( OletxTransactionOutcome.Aborted == outcome ) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED; } else // we must not know the outcome yet. { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; StartReenlistThread(); } } catch ( COMException ex ) { if ( NativeMethods.XACT_E_CONNECTION_DOWN == ex.ErrorCode ) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; this.ResourceManagerShim = null; StartReenlistThread(); if ( DiagnosticTrace.Verbose ) { ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), ex ); } } else { throw; } } finally { localResourceManagerShim = null; } // Now create our enlistment to tell the client the outcome. OletxEnlistment enlistment = new OletxEnlistment( enlistmentNotification, xactStatus, oletxRecoveryInformation.proxyRecoveryInformation, this ); return enlistment; }
internal OletxEnlistment Reenlist(int prepareInfoLength, byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification) { OletxRecoveryInformation information; OletxTransactionOutcome notKnownYet = OletxTransactionOutcome.NotKnownYet; OletxTransactionStatus xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE; MemoryStream serializationStream = new MemoryStream(prepareInfo); IFormatter formatter = new BinaryFormatter(); try { information = formatter.Deserialize(serializationStream) as OletxRecoveryInformation; } catch (SerializationException exception2) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo", exception2); } if (information == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo"); } byte[] b = new byte[0x10]; for (int i = 0; i < 0x10; i++) { b[i] = information.proxyRecoveryInformation[i + 0x10]; } Guid guid = new Guid(b); if (guid != this.resourceManagerIdentifier) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("ResourceManagerIdDoesNotMatchRecoveryInformation"), null); } IResourceManagerShim resourceManagerShim = null; try { resourceManagerShim = this.ResourceManagerShim; if (resourceManagerShim == null) { throw new COMException(System.Transactions.SR.GetString("DtcTransactionManagerUnavailable"), System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN); } resourceManagerShim.Reenlist(Convert.ToUInt32(information.proxyRecoveryInformation.Length, CultureInfo.InvariantCulture), information.proxyRecoveryInformation, out notKnownYet); if (OletxTransactionOutcome.Committed == notKnownYet) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED; } else if (OletxTransactionOutcome.Aborted == notKnownYet) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED; } else { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; this.StartReenlistThread(); } } catch (COMException exception) { if (System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN != exception.ErrorCode) { throw; } xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; this.ResourceManagerShim = null; this.StartReenlistThread(); if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } finally { resourceManagerShim = null; } return(new OletxEnlistment(enlistmentNotification, xactStatus, information.proxyRecoveryInformation, this)); }
internal OletxEnlistment ReenlistTransaction(Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotificationInternal enlistmentNotification) { if (recoveryInformation == null) { throw new ArgumentNullException("recoveryInformation"); } if (enlistmentNotification == null) { throw new ArgumentNullException("enlistmentNotification"); } OletxResourceManager manager = this.RegisterResourceManager(resourceManagerIdentifier); if (manager == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "resourceManagerIdentifier"); } if (manager.RecoveryCompleteCalledByApplication) { throw new InvalidOperationException(System.Transactions.SR.GetString("ReenlistAfterRecoveryComplete")); } return manager.Reenlist(recoveryInformation.Length, recoveryInformation, enlistmentNotification); }
public void Phase0Request(bool abortingHint) { IEnlistmentNotificationInternal iEnlistmentNotification = null; OletxEnlistmentState active = OletxEnlistmentState.Active; OletxCommittableTransaction committableTransaction = null; bool flag = false; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxEnlistment.Phase0Request"); } committableTransaction = base.oletxTransaction.realOletxTransaction.committableTransaction; if ((committableTransaction != null) && !committableTransaction.CommitCalled) { flag = true; } lock (this) { this.aborting = abortingHint; if (this.state == OletxEnlistmentState.Active) { if ((this.aborting || flag) || this.tmWentDown) { if (this.phase0Shim != null) { try { this.phase0Shim.Phase0Done(false); } catch (COMException exception) { if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } } } else { active = this.state = OletxEnlistmentState.Phase0Preparing; iEnlistmentNotification = this.iEnlistmentNotification; } } } if (iEnlistmentNotification != null) { if (OletxEnlistmentState.Phase0Preparing != active) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxEnlistment.Phase0Request"); } return; } byte[] buffer = this.transactionGuid.ToByteArray(); byte[] buffer2 = base.oletxResourceManager.resourceManagerIdentifier.ToByteArray(); byte[] buffer4 = new byte[buffer.Length + buffer2.Length]; Thread.MemoryBarrier(); this.proxyPrepareInfoByteArray = buffer4; int index = 0; for (index = 0; index < buffer.Length; index++) { this.proxyPrepareInfoByteArray[index] = buffer[index]; } for (index = 0; index < buffer2.Length; index++) { this.proxyPrepareInfoByteArray[buffer.Length + index] = buffer2[index]; } OletxRecoveryInformation thingToConvert = new OletxRecoveryInformation(this.proxyPrepareInfoByteArray); byte[] resourceManagerRecoveryInformation = TransactionManager.ConvertToByteArray(thingToConvert); this.prepareInfoByteArray = TransactionManager.GetRecoveryInformation(base.oletxResourceManager.oletxTransactionManager.CreationNodeName, resourceManagerRecoveryInformation); if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Prepare); } iEnlistmentNotification.Prepare(this); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxEnlistment.Phase0Request"); } }
internal OletxEnlistment Reenlist(byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification) { OletxTransactionOutcome outcome = OletxTransactionOutcome.NotKnownYet; OletxTransactionStatus xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE; if (prepareInfo == null) { throw new ArgumentException(SR.InvalidArgument, nameof(prepareInfo)); } // Verify that the resource manager guid in the recovery info matches that of the calling resource manager. byte[] rmGuidArray = new byte[16]; for (int i = 0; i < 16; i++) { rmGuidArray[i] = prepareInfo[i + 16]; } Guid rmGuid = new(rmGuidArray); if (rmGuid != ResourceManagerIdentifier) { throw TransactionException.Create(TraceSourceType.TraceSourceOleTx, SR.ResourceManagerIdDoesNotMatchRecoveryInformation, null); } // Ask the proxy resource manager to reenlist. ResourceManagerShim?localResourceManagerShim = null; try { localResourceManagerShim = ResourceManagerShim; if (localResourceManagerShim == null) { // The TM must be down. Throw the exception that will get caught below and will cause // the enlistment to start the ReenlistThread. The TMDown thread will be trying to reestablish // connection with the TM and will start the reenlist thread when it does. throw new COMException(SR.DtcTransactionManagerUnavailable, OletxHelper.XACT_E_CONNECTION_DOWN); } // Only wait for 5 milliseconds. If the TM doesn't have the outcome now, we will // put the enlistment on the reenlistList for later processing. localResourceManagerShim.Reenlist(prepareInfo, out outcome); if (OletxTransactionOutcome.Committed == outcome) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED; } else if (OletxTransactionOutcome.Aborted == outcome) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED; } else // we must not know the outcome yet. { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; StartReenlistThread(); } } catch (COMException ex) when(ex.ErrorCode == OletxHelper.XACT_E_CONNECTION_DOWN) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; ResourceManagerShim = null; StartReenlistThread(); TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.ExceptionConsumed(TraceSourceType.TraceSourceOleTx, ex); } } finally { localResourceManagerShim = null; } // Now create our enlistment to tell the client the outcome. return(new OletxEnlistment(enlistmentNotification, xactStatus, prepareInfo, this)); }
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 OletxEnlistment( IEnlistmentNotificationInternal enlistmentNotification, OletxTransactionStatus xactStatus, byte[] prepareInfoByteArray, OletxResourceManager oletxResourceManager ) : base( oletxResourceManager, null ) { 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 = false; this.iEnlistmentNotification = enlistmentNotification; this.state = OletxEnlistmentState.Active; // Do this before we do any tracing because it will affect the trace identifiers that we generate. Debug.Assert( ( null != prepareInfoByteArray ), "OletxEnlistment.ctor - null oletxTransaction without a prepareInfoByteArray" ); int prepareInfoLength = prepareInfoByteArray.Length; this.proxyPrepareInfoByteArray = new byte[prepareInfoLength]; Array.Copy(prepareInfoByteArray, proxyPrepareInfoByteArray, prepareInfoLength); byte[] txGuidByteArray = new byte[16]; Array.Copy(proxyPrepareInfoByteArray, txGuidByteArray, 16); this.transactionGuid = new Guid( txGuidByteArray ); this.transactionGuidString = this.transactionGuid.ToString(); // If this is being created as part of a Reenlist and we already know the // outcome, then tell the application. switch (xactStatus) { case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED: { this.state = OletxEnlistmentState.Aborting; if ( DiagnosticTrace.Verbose ) { EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, NotificationCall.Rollback ); } iEnlistmentNotification.Rollback( this ); break; } case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED: { this.state = OletxEnlistmentState.Committing; // We are going to send the notification to the RM. We need to put the // enlistment on the reenlistPendingList. We lock the reenlistList because // we have decided that is the lock that protects both lists. The entry will // be taken off the reenlistPendingList when the enlistment has // EnlistmentDone called on it. The enlistment will call // RemoveFromReenlistPending. lock ( oletxResourceManager.reenlistList ) { oletxResourceManager.reenlistPendingList.Add( this ); } if ( DiagnosticTrace.Verbose ) { EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, NotificationCall.Commit ); } iEnlistmentNotification.Commit( this ); break; } case OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED: { this.state = OletxEnlistmentState.Prepared; lock ( oletxResourceManager.reenlistList ) { oletxResourceManager.reenlistList.Add( this ); oletxResourceManager.StartReenlistThread(); } break; } default: { if ( DiagnosticTrace.Critical ) { InternalErrorTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), SR.GetString( SR.OletxEnlistmentUnexpectedTransactionStatus ) ); } throw TransactionException.Create( SR.GetString( SR.TraceSourceOletx ), SR.GetString( SR.OletxEnlistmentUnexpectedTransactionStatus ), null ); } } if ( DiagnosticTrace.Information ) { EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, EnlistmentType.Durable, EnlistmentOptions.None ); } // Always do this last in case anything prior to this fails. AddToEnlistmentTable(); }
public bool PrepareRequest(bool singlePhase, byte[] prepareInfo) { IEnlistmentShim enlistmentShim = null; OletxEnlistmentState active = OletxEnlistmentState.Active; IEnlistmentNotificationInternal iEnlistmentNotification = null; OletxRecoveryInformation thingToConvert = null; lock (this) { if (this.state == OletxEnlistmentState.Active) { active = this.state = OletxEnlistmentState.Preparing; } else { active = this.state; } iEnlistmentNotification = this.iEnlistmentNotification; enlistmentShim = this.EnlistmentShim; base.oletxTransaction.realOletxTransaction.TooLateForEnlistments = true; } if (OletxEnlistmentState.Preparing == active) { thingToConvert = new OletxRecoveryInformation(prepareInfo); this.isSinglePhase = singlePhase; long length = prepareInfo.Length; this.proxyPrepareInfoByteArray = new byte[length]; Array.Copy(prepareInfo, this.proxyPrepareInfoByteArray, length); if (this.isSinglePhase && this.canDoSinglePhase) { ISinglePhaseNotificationInternal internal3 = (ISinglePhaseNotificationInternal) iEnlistmentNotification; this.state = OletxEnlistmentState.SinglePhaseCommitting; if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.SinglePhaseCommit); } internal3.SinglePhaseCommit(this); return true; } byte[] resourceManagerRecoveryInformation = TransactionManager.ConvertToByteArray(thingToConvert); this.state = OletxEnlistmentState.Preparing; this.prepareInfoByteArray = TransactionManager.GetRecoveryInformation(base.oletxResourceManager.oletxTransactionManager.CreationNodeName, resourceManagerRecoveryInformation); if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Prepare); } iEnlistmentNotification.Prepare(this); return false; } if (OletxEnlistmentState.Prepared == active) { try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.Prepared); return false; } catch (COMException exception3) { OletxTransactionManager.ProxyException(exception3); throw; } } if (OletxEnlistmentState.Done == active) { try { bool flag; try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.ReadOnly); flag = true; } finally { this.FinishEnlistment(); } return flag; } catch (COMException exception2) { OletxTransactionManager.ProxyException(exception2); throw; } } try { enlistmentShim.PrepareRequestDone(OletxPrepareVoteType.Failed); } catch (COMException exception) { if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } return true; }
internal OletxEnlistment Reenlist(int prepareInfoLength, byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification) { OletxRecoveryInformation information; OletxTransactionOutcome notKnownYet = OletxTransactionOutcome.NotKnownYet; OletxTransactionStatus xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE; MemoryStream serializationStream = new MemoryStream(prepareInfo); IFormatter formatter = new BinaryFormatter(); try { information = formatter.Deserialize(serializationStream) as OletxRecoveryInformation; } catch (SerializationException exception2) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo", exception2); } if (information == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo"); } byte[] b = new byte[0x10]; for (int i = 0; i < 0x10; i++) { b[i] = information.proxyRecoveryInformation[i + 0x10]; } Guid guid = new Guid(b); if (guid != this.resourceManagerIdentifier) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("ResourceManagerIdDoesNotMatchRecoveryInformation"), null); } IResourceManagerShim resourceManagerShim = null; try { resourceManagerShim = this.ResourceManagerShim; if (resourceManagerShim == null) { throw new COMException(System.Transactions.SR.GetString("DtcTransactionManagerUnavailable"), System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN); } resourceManagerShim.Reenlist(Convert.ToUInt32(information.proxyRecoveryInformation.Length, CultureInfo.InvariantCulture), information.proxyRecoveryInformation, out notKnownYet); if (OletxTransactionOutcome.Committed == notKnownYet) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED; } else if (OletxTransactionOutcome.Aborted == notKnownYet) { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED; } else { xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; this.StartReenlistThread(); } } catch (COMException exception) { if (System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN != exception.ErrorCode) { throw; } xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED; this.ResourceManagerShim = null; this.StartReenlistThread(); if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception); } } finally { resourceManagerShim = null; } return new OletxEnlistment(enlistmentNotification, xactStatus, information.proxyRecoveryInformation, this); }
internal IPromotedEnlistment EnlistVolatile( IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions ) { if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "OletxTransaction.EnlistVolatile( IEnlistmentNotificationInternal )" ); } Debug.Assert( null != enlistmentNotification, "Argument is null" ); Debug.Assert( ( 0 == this.disposed ), "OletxTransction object is disposed" ); if ( this.realOletxTransaction == null || this.realOletxTransaction.TooLateForEnlistments ) { throw TransactionException.Create(SR.GetString(SR.TraceSourceOletx), SR.GetString(SR.TooLate), null, this.DistributedTxId); } IPromotedEnlistment enlistment = realOletxTransaction.EnlistVolatile( enlistmentNotification, enlistmentOptions, this ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "OletxTransaction.EnlistVolatile( IEnlistmentNotificationInternal )" ); } return enlistment; }
internal IPromotedEnlistment EnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) { return(this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction)); }
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 ReenlistTransaction(Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotificationInternal enlistmentNotification) { if (recoveryInformation == null) { throw new ArgumentNullException("recoveryInformation"); } if (enlistmentNotification == null) { throw new ArgumentNullException("enlistmentNotification"); } OletxResourceManager manager = this.RegisterResourceManager(resourceManagerIdentifier); if (manager == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "resourceManagerIdentifier"); } if (manager.RecoveryCompleteCalledByApplication) { throw new InvalidOperationException(System.Transactions.SR.GetString("ReenlistAfterRecoveryComplete")); } return(manager.Reenlist(recoveryInformation.Length, recoveryInformation, enlistmentNotification)); }
internal OletxEnlistment EnlistDurable( OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions) { ResourceManagerShim?localResourceManagerShim; Debug.Assert(oletxTransaction != null, "Argument is null"); Debug.Assert(enlistmentNotification != null, "Argument is null"); EnlistmentShim enlistmentShim; Phase0EnlistmentShim phase0Shim; Guid txUow = Guid.Empty; bool undecidedEnlistmentsIncremented = false; // Create our enlistment object. OletxEnlistment enlistment = new( canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction); bool enlistmentSucceeded = false; try { if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0) { oletxTransaction.RealTransaction.IncrementUndecidedEnlistments(); undecidedEnlistmentsIncremented = true; } // This entire sequence needs to be executed before we can go on. lock (enlistment) { try { // Do the enlistment on the proxy. localResourceManagerShim = ResourceManagerShim; if (localResourceManagerShim == null) { // The TM must be down. Throw the appropriate exception. throw TransactionManagerCommunicationException.Create(SR.TraceSourceOletx, null); } if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0) { oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(enlistment, out phase0Shim); enlistment.Phase0EnlistmentShim = phase0Shim; } localResourceManagerShim.Enlist(oletxTransaction.RealTransaction.TransactionShim, enlistment, 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 (comException.ErrorCode == OletxHelper.XACT_E_TOOMANY_ENLISTMENTS) { throw TransactionException.Create( SR.OletxTooManyEnlistments, comException, enlistment == null ? Guid.Empty : enlistment.DistributedTxId); } OletxTransactionManager.ProxyException(comException); throw; } } enlistmentSucceeded = true; } finally { if (!enlistmentSucceeded && (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 && undecidedEnlistmentsIncremented) { oletxTransaction.RealTransaction.DecrementUndecidedEnlistments(); } } return(enlistment); }