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 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 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 ); } } }