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 Commit() { OletxVolatileEnlistmentState active = OletxVolatileEnlistmentState.Active; IEnlistmentNotificationInternal iEnlistmentNotification = null; lock (this) { if (OletxVolatileEnlistmentState.Prepared == this.state) { active = this.state = OletxVolatileEnlistmentState.Committing; iEnlistmentNotification = this.iEnlistmentNotification; } else { active = this.state; } } if (OletxVolatileEnlistmentState.Committing == active) { if (iEnlistmentNotification != null) { if (DiagnosticTrace.Verbose) { EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, NotificationCall.Commit); } iEnlistmentNotification.Commit(this); return; } if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } if (OletxVolatileEnlistmentState.Done != active) { if (DiagnosticTrace.Critical) { InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), ""); } throw new InvalidOperationException(System.Transactions.SR.GetString("InternalError")); } }
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(); }