|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Threading;
namespace System.Transactions
{
// Base class for all enlistment states
internal abstract class EnlistmentState
{
internal abstract void EnterState(InternalEnlistment enlistment);
internal static EnlistmentStatePromoted? _enlistmentStatePromoted;
// Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) )
private static object? s_classSyncObject;
internal static EnlistmentStatePromoted EnlistmentStatePromoted =>
LazyInitializer.EnsureInitialized(ref _enlistmentStatePromoted, ref s_classSyncObject, () => new EnlistmentStatePromoted());
internal virtual void EnlistmentDone(InternalEnlistment enlistment)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void Prepared(InternalEnlistment enlistment)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ForceRollback(InternalEnlistment enlistment, Exception? e)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void Committed(InternalEnlistment enlistment)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void Aborted(InternalEnlistment enlistment, Exception? e)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void InDoubt(InternalEnlistment enlistment, Exception? e)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual byte[] RecoveryInformation(InternalEnlistment enlistment)
{
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void InternalAborted(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void InternalCommitted(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void InternalIndoubt(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ChangeStateCommitting(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ChangeStatePromoted(InternalEnlistment enlistment, IPromotedEnlistment promotedEnlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ChangeStateDelegated(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ChangeStatePreparing(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
internal virtual void ChangeStateSinglePhaseCommit(InternalEnlistment enlistment)
{
Debug.Fail($"Invalid Event for InternalEnlistment State; Current State: {GetType()}");
throw TransactionException.CreateEnlistmentStateException(null, enlistment == null ? Guid.Empty : enlistment.DistributedTxId);
}
}
internal sealed class EnlistmentStatePromoted : EnlistmentState
{
internal override void EnterState(InternalEnlistment enlistment)
{
enlistment.State = this;
}
internal override void EnlistmentDone(InternalEnlistment enlistment)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.EnlistmentDone();
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override void Prepared(InternalEnlistment enlistment)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.Prepared();
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override void ForceRollback(InternalEnlistment enlistment, Exception? e)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.ForceRollback(e);
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override void Committed(InternalEnlistment enlistment)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.Committed();
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override void Aborted(InternalEnlistment enlistment, Exception? e)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.Aborted(e);
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override void InDoubt(InternalEnlistment enlistment, Exception? e)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
enlistment.PromotedEnlistment.InDoubt(e);
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
internal override byte[] RecoveryInformation(InternalEnlistment enlistment)
{
Monitor.Exit(enlistment.SyncRoot);
try
{
Debug.Assert(enlistment.PromotedEnlistment != null);
return enlistment.PromotedEnlistment.GetRecoveryInformation();
}
finally
{
Monitor.Enter(enlistment.SyncRoot);
}
}
}
}
|