// ITransactionPhase0NotifyAsync public void Phase0Request( bool abortingHint ) { IEnlistmentNotificationInternal localEnlistmentNotification = null; OletxEnlistmentState localState = OletxEnlistmentState.Active; OletxCommittableTransaction committableTx = null; bool commitNotYetCalled = false; if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "OletxEnlistment.Phase0Request" ); } committableTx = this.oletxTransaction.realOletxTransaction.committableTransaction; if ( null != committableTx ) { // We are dealing with the committable transaction. If Commit or BeginCommit has NOT been // called, then we are dealing with a situation where the TM went down and we are getting // a bogus Phase0Request with abortHint = false (COMPlus bug 36760/36758). This is an attempt // to not send the app a Prepare request when we know the transaction is going to abort. if (!committableTx.CommitCalled ) { commitNotYetCalled = true; } } lock ( this ) { this.aborting = abortingHint; // The app may have already called EnlistmentDone. If this occurs, don't bother sending // the notification to the app and we don't need to tell the proxy. if ( OletxEnlistmentState.Active == state ) { // If we got an abort hint or we are the committable transaction and Commit has not yet been called or the TM went down, // we don't want to do any more work on the transaction. The abort notifications will be sent by the phase 1 // enlistment if ( ( this.aborting ) || ( commitNotYetCalled ) || ( this.tmWentDown ) ) { // There is a possible ---- where we could get the Phase0Request before we are given the // shim. In that case, we will vote "no" when we are given the shim. if ( null != this.phase0Shim ) { try { this.phase0Shim.Phase0Done( false ); } // I am not going to check for XACT_E_PROTOCOL here because that check is a workaround for a bug // that only shows up if abortingHint is false. catch ( COMException ex ) { if ( DiagnosticTrace.Verbose ) { ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), ex ); } } } } else { localState = state = OletxEnlistmentState.Phase0Preparing; localEnlistmentNotification = iEnlistmentNotification; } } } // Tell the application to do the work. if ( null != localEnlistmentNotification ) { if ( OletxEnlistmentState.Phase0Preparing == localState ) { byte[] txGuidArray = transactionGuid.ToByteArray(); byte[] rmGuidArray = oletxResourceManager.resourceManagerIdentifier.ToByteArray(); byte[] temp = new byte[txGuidArray.Length + rmGuidArray.Length]; Thread.MemoryBarrier(); this.proxyPrepareInfoByteArray = temp; int index = 0; for ( index = 0; index < txGuidArray.Length; index++ ) { proxyPrepareInfoByteArray[index] = txGuidArray[index]; } for ( index = 0; index < rmGuidArray.Length; index++ ) { proxyPrepareInfoByteArray[txGuidArray.Length + index] = rmGuidArray[index]; } OletxRecoveryInformation oletxRecoveryInformation = new OletxRecoveryInformation( proxyPrepareInfoByteArray ); byte[] oletxRecoveryInformationByteArray = TransactionManager.ConvertToByteArray( oletxRecoveryInformation ); // this.prepareInfoByteArray = TransactionManager.GetRecoveryInformation( oletxResourceManager.oletxTransactionManager.CreationNodeName, oletxRecoveryInformationByteArray ); if ( DiagnosticTrace.Verbose ) { EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, NotificationCall.Prepare ); } localEnlistmentNotification.Prepare( this ); } else { // We must have had a ---- between EnlistmentDone and the proxy telling // us Phase0Request. Just return. if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "OletxEnlistment.Phase0Request" ); } return; } } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "OletxEnlistment.Phase0Request" ); } }
// ITranactionResourceAsync.PrepareRequest public bool PrepareRequest( bool singlePhase, byte[] prepareInfo ) { IEnlistmentShim localEnlistmentShim = null; OletxEnlistmentState localState = OletxEnlistmentState.Active; IEnlistmentNotificationInternal localEnlistmentNotification = null; OletxRecoveryInformation oletxRecoveryInformation = null; bool enlistmentDone; lock ( this ) { if ( OletxEnlistmentState.Active == state ) { localState = state = OletxEnlistmentState.Preparing; } else { // We must have done the prepare work in Phase0, so just remember what state we are // in now. localState = state; } localEnlistmentNotification = iEnlistmentNotification; localEnlistmentShim = this.EnlistmentShim; this.oletxTransaction.realOletxTransaction.TooLateForEnlistments = true; } // If we went to Preparing state, send the app // a prepare request. if ( OletxEnlistmentState.Preparing == localState ) { oletxRecoveryInformation = new OletxRecoveryInformation( prepareInfo ); this.isSinglePhase = singlePhase; // Store the prepare info we are given. Debug.Assert(this.proxyPrepareInfoByteArray == null, "Unexpected value in this.proxyPrepareInfoByteArray"); long arrayLength = prepareInfo.Length; this.proxyPrepareInfoByteArray = new Byte[arrayLength]; Array.Copy(prepareInfo, this.proxyPrepareInfoByteArray, arrayLength); if ( this.isSinglePhase && this.canDoSinglePhase ) { ISinglePhaseNotificationInternal singlePhaseNotification = (ISinglePhaseNotificationInternal) localEnlistmentNotification; state = OletxEnlistmentState.SinglePhaseCommitting; // We don't call DecrementUndecidedEnlistments for Phase1 enlistments. if ( DiagnosticTrace.Verbose ) { EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, NotificationCall.SinglePhaseCommit ); } singlePhaseNotification.SinglePhaseCommit( this ); enlistmentDone = true; } else { // We need to turn the oletxRecoveryInformation into a byte array. byte[] oletxRecoveryInformationByteArray = TransactionManager.ConvertToByteArray( oletxRecoveryInformation ); state = OletxEnlistmentState.Preparing; // this.prepareInfoByteArray = TransactionManager.GetRecoveryInformation( oletxResourceManager.oletxTransactionManager.CreationNodeName, oletxRecoveryInformationByteArray ); if ( DiagnosticTrace.Verbose ) { EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.InternalTraceIdentifier, NotificationCall.Prepare ); } localEnlistmentNotification.Prepare( this ); enlistmentDone = false; } } else if ( OletxEnlistmentState.Prepared == localState ) { // We must have done our prepare work during Phase0 so just vote Yes. try { localEnlistmentShim.PrepareRequestDone( OletxPrepareVoteType.Prepared ); enlistmentDone = false; } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); throw; } } else if ( OletxEnlistmentState.Done == localState ) { try { // This was an early vote. Respond ReadOnly try { localEnlistmentShim.PrepareRequestDone( OletxPrepareVoteType.ReadOnly ); enlistmentDone = true; } finally { FinishEnlistment(); } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); throw; } } else { // Any other state means we should vote NO to the proxy. try { localEnlistmentShim.PrepareRequestDone( OletxPrepareVoteType.Failed ); } catch ( COMException ex ) { // No point in rethrowing this. We are not on an app thread and we have already told // the app that the transaction is aborting. When the app calls EnlistmentDone, we will // do the final release of the ITransactionEnlistmentAsync. if ( DiagnosticTrace.Verbose ) { ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), ex ); } } enlistmentDone = true; } return enlistmentDone; }
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); }
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"); } }
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; }