internal virtual void PromoteEnlistmentsAndOutcome(InternalTransaction tx)
{
// Failures from this point on will simply abort the two types of transaction
// seperately. Note that this may cause duplicate internal aborted events to
// be sent to some of the enlistments however the enlistment state machines
// can handle the duplicate notification.
bool enlistmentsPromoted = false;
// Tell the real transaction that we want a callback for the outcome.
tx.PromotedTransaction.RealTransaction.InternalTransaction = tx;
// Promote Phase 0 Volatiles
try
{
enlistmentsPromoted = PromotePhaseVolatiles(tx, ref tx._phase0Volatiles, true);
}
catch (TransactionException te)
{
// Record the exception information.
tx._innerException = te;
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
etwLog.ExceptionConsumed(te);
}
return;
}
finally
{
if (!enlistmentsPromoted)
{
tx.PromotedTransaction.Rollback();
// Now abort this transaction.
tx.State.ChangeStateAbortedDuringPromotion(tx);
}
}
enlistmentsPromoted = false;
try
{
enlistmentsPromoted = PromotePhaseVolatiles(tx, ref tx._phase1Volatiles, false);
}
catch (TransactionException te)
{
// Record the exception information.
tx._innerException = te;
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
etwLog.ExceptionConsumed(te);
}
return;
}
finally
{
if (!enlistmentsPromoted)
{
tx.PromotedTransaction.Rollback();
// Now abort this transaction.
tx.State.ChangeStateAbortedDuringPromotion(tx);
}
}
enlistmentsPromoted = false;
// Promote the durable enlistment
try
{
enlistmentsPromoted = PromoteDurable(tx);
}
catch (TransactionException te)
{
// Record the exception information.
tx._innerException = te;
TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
if (etwLog.IsEnabled())
{
etwLog.ExceptionConsumed(te);
}
return;
}
finally
{
if (!enlistmentsPromoted)
{
tx.PromotedTransaction.Rollback();
// Now abort this transaction.
tx.State.ChangeStateAbortedDuringPromotion(tx);
}
}
}