Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / VolatileEnlistmentMultiplexing.cs / 1305376 / VolatileEnlistmentMultiplexing.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Transactions
{
using System;
using System.Diagnostics;
using System.Threading;
using System.Transactions;
using System.Transactions.Diagnostics;
// The volatile Demultiplexer is a fanout point for promoted volatile enlistments.
// When a transaction is promoted a single volatile enlistment is created in the new
// transaction for all volitile enlistments on the transaction. When the VolatileDemux
// receives a preprepare it will fan that notification out to all of the enlistments
// on the transaction. When it has gathered all of the responses it will send a
// single vote back to the DistributedTransactionManager.
internal abstract class VolatileDemultiplexer : IEnlistmentNotificationInternal
{
// Reference the transactions so that we have access to it's enlistments
protected InternalTransaction transaction;
// Store the IVolatileEnlistment interface to call back to the Distributed TM
internal IPromotedEnlistment oletxEnlistment;
internal IPromotedEnlistment preparingEnlistment;
public VolatileDemultiplexer( InternalTransaction transaction )
{
this.transaction = transaction;
}
internal void BroadcastCommitted( ref VolatileEnlistmentSet volatiles )
{
// Broadcast preprepare to the volatile subordinates
for( int i = 0; i < volatiles.volatileEnlistmentCount; i++ )
{
volatiles.volatileEnlistments [i].twoPhaseState.InternalCommitted(
volatiles.volatileEnlistments [i] );
}
}
// This broadcast is used by the state machines and therefore must be internal.
internal void BroadcastRollback( ref VolatileEnlistmentSet volatiles )
{
// Broadcast preprepare to the volatile subordinates
for( int i = 0; i < volatiles.volatileEnlistmentCount; i++ )
{
volatiles.volatileEnlistments [i].twoPhaseState.InternalAborted(
volatiles.volatileEnlistments [i] );
}
}
internal void BroadcastInDoubt( ref VolatileEnlistmentSet volatiles )
{
// Broadcast preprepare to the volatile subordinates
for( int i = 0; i < volatiles.volatileEnlistmentCount; i++ )
{
volatiles.volatileEnlistments [i].twoPhaseState.InternalIndoubt(
volatiles.volatileEnlistments [i] );
}
}
// Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) )
private static object classSyncObject;
internal static object ClassSyncObject
{
get
{
if( classSyncObject == null )
{
object o = new object();
Interlocked.CompareExchange( ref classSyncObject, o, null );
}
return classSyncObject;
}
}
private static WaitCallback prepareCallback;
private static WaitCallback PrepareCallback
{
get
{
if( prepareCallback == null )
{
lock( ClassSyncObject )
{
if( prepareCallback == null )
{
WaitCallback temp = new WaitCallback( PoolablePrepare );
Thread.MemoryBarrier();
prepareCallback = temp;
}
}
}
return prepareCallback;
}
}
protected static void PoolablePrepare( object state )
{
VolatileDemultiplexer demux = (VolatileDemultiplexer) state;
// Don't block an enlistment thread (or a thread pool thread). So
// try to get the transaction lock but if unsuccessfull give up and
// queue this operation to try again later.
bool tookLock = false;
try
{
System.Threading.Monitor.TryEnter(demux.transaction, 250, ref tookLock);
if (tookLock)
{
demux.InternalPrepare();
}
else
{
if (!ThreadPool.QueueUserWorkItem(PrepareCallback, demux))
{
throw TransactionException.CreateInvalidOperationException(
SR.GetString(SR.TraceSourceLtm),
SR.GetString(SR.UnexpectedFailureOfThreadPool),
null
);
}
}
}
finally
{
if (tookLock)
{
System.Threading.Monitor.Exit(demux.transaction);
}
}
}
private static WaitCallback commitCallback;
private static WaitCallback CommitCallback
{
get
{
if( commitCallback == null )
{
lock( ClassSyncObject )
{
if( commitCallback == null )
{
WaitCallback temp = new WaitCallback( PoolableCommit );
Thread.MemoryBarrier();
commitCallback = temp;
}
}
}
return commitCallback;
}
}
protected static void PoolableCommit( object state )
{
VolatileDemultiplexer demux = (VolatileDemultiplexer) state;
// Don't block an enlistment thread (or a thread pool thread). So
// try to get the transaction lock but if unsuccessfull give up and
// queue this operation to try again later.
bool tookLock = false;
try
{
System.Threading.Monitor.TryEnter(demux.transaction, 250, ref tookLock);
if (tookLock)
{
demux.InternalCommit();
}
else
{
if (!ThreadPool.QueueUserWorkItem(CommitCallback, demux))
{
throw TransactionException.CreateInvalidOperationException(
SR.GetString(SR.TraceSourceLtm),
SR.GetString(SR.UnexpectedFailureOfThreadPool),
null
);
}
}
}
finally
{
if (tookLock)
{
System.Threading.Monitor.Exit(demux.transaction);
}
}
}
private static WaitCallback rollbackCallback;
private static WaitCallback RollbackCallback
{
get
{
if( rollbackCallback == null )
{
lock( ClassSyncObject )
{
if(rollbackCallback == null )
{
WaitCallback temp = new WaitCallback( PoolableRollback );
Thread.MemoryBarrier();
rollbackCallback = temp;
}
}
}
return rollbackCallback;
}
}
protected static void PoolableRollback( object state )
{
VolatileDemultiplexer demux = (VolatileDemultiplexer) state;
// Don't block an enlistment thread (or a thread pool thread). So
// try to get the transaction lock but if unsuccessfull give up and
// queue this operation to try again later.
bool tookLock = false;
try
{
System.Threading.Monitor.TryEnter(demux.transaction, 250, ref tookLock);
if (tookLock)
{
demux.InternalRollback();
}
else
{
if (!ThreadPool.QueueUserWorkItem(RollbackCallback, demux))
{
throw TransactionException.CreateInvalidOperationException(
SR.GetString(SR.TraceSourceLtm),
SR.GetString(SR.UnexpectedFailureOfThreadPool),
null
);
}
}
}
finally
{
if (tookLock)
{
System.Threading.Monitor.Exit(demux.transaction);
}
}
}
private static WaitCallback inDoubtCallback;
private static WaitCallback InDoubtCallback
{
get
{
if(inDoubtCallback == null )
{
lock( ClassSyncObject )
{
if(inDoubtCallback == null )
{
WaitCallback temp = new WaitCallback( PoolableInDoubt );
Thread.MemoryBarrier();
inDoubtCallback = temp;
}
}
}
return inDoubtCallback;
}
}
protected static void PoolableInDoubt( object state )
{
VolatileDemultiplexer demux = (VolatileDemultiplexer) state;
// Don't block an enlistment thread (or a thread pool thread). So
// try to get the transaction lock but if unsuccessfull give up and
// queue this operation to try again later.
bool tookLock = false;
try
{
System.Threading.Monitor.TryEnter(demux.transaction, 250, ref tookLock);
if (tookLock)
{
demux.InternalInDoubt();
}
else
{
if (!ThreadPool.QueueUserWorkItem(InDoubtCallback, demux))
{
throw TransactionException.CreateInvalidOperationException(
SR.GetString(SR.TraceSourceLtm),
SR.GetString(SR.UnexpectedFailureOfThreadPool),
null
);
}
}
}
finally
{
if (tookLock)
{
System.Threading.Monitor.Exit(demux.transaction);
}
}
}
protected abstract void InternalPrepare();
protected abstract void InternalCommit();
protected abstract void InternalRollback();
protected abstract void InternalInDoubt();
#region IEnlistmentNotification Members
// Fanout Preprepare notifications
public abstract void Prepare( IPromotedEnlistment en );
public abstract void Commit( IPromotedEnlistment en );
public abstract void Rollback( IPromotedEnlistment en );
public abstract void InDoubt( IPromotedEnlistment en );
#endregion
}
// This class implements the phase 0 version of a volatile demux.
internal class Phase0VolatileDemultiplexer : VolatileDemultiplexer
{
public Phase0VolatileDemultiplexer( InternalTransaction transaction ) : base( transaction ) {}
protected override void InternalPrepare()
{
try
{
this.transaction.State.ChangeStatePromotedPhase0( this.transaction );
}
catch( TransactionAbortedException e )
{
this.oletxEnlistment.ForceRollback(e);
if ( DiagnosticTrace.Verbose )
{
ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
e );
}
}
catch( TransactionInDoubtException e )
{
this.oletxEnlistment.EnlistmentDone();
if ( DiagnosticTrace.Verbose )
{
ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
e );
}
}
}
protected override void InternalCommit()
{
// Respond immediately to the TM
this.oletxEnlistment.EnlistmentDone();
this.transaction.State.ChangeStatePromotedCommitted( this.transaction );
}
protected override void InternalRollback()
{
// Respond immediately to the TM
this.oletxEnlistment.EnlistmentDone();
this.transaction.State.ChangeStatePromotedAborted( this.transaction );
}
protected override void InternalInDoubt()
{
this.transaction.State.InDoubtFromDtc( this.transaction );
}
#region IEnlistmentNotification Members
// Fanout Preprepare notifications
public override void Prepare( IPromotedEnlistment en )
{
this.preparingEnlistment = en;
PoolablePrepare( this );
}
public override void Commit( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableCommit( this );
}
public override void Rollback( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableRollback( this );
}
public override void InDoubt( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableInDoubt( this );
}
#endregion
}
// This class implements the phase 1 version of a volatile demux.
internal class Phase1VolatileDemultiplexer : VolatileDemultiplexer
{
public Phase1VolatileDemultiplexer( InternalTransaction transaction ) : base( transaction ) {}
protected override void InternalPrepare()
{
try
{
this.transaction.State.ChangeStatePromotedPhase1( this.transaction );
}
catch( TransactionAbortedException e )
{
this.oletxEnlistment.ForceRollback(e);
if ( DiagnosticTrace.Verbose )
{
ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
e );
}
}
catch( TransactionInDoubtException e )
{
this.oletxEnlistment.EnlistmentDone();
if ( DiagnosticTrace.Verbose )
{
ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
e );
}
}
}
protected override void InternalCommit()
{
// Respond immediately to the TM
this.oletxEnlistment.EnlistmentDone();
this.transaction.State.ChangeStatePromotedCommitted( this.transaction );
}
protected override void InternalRollback()
{
// Respond immediately to the TM
this.oletxEnlistment.EnlistmentDone();
this.transaction.State.ChangeStatePromotedAborted( this.transaction );
}
protected override void InternalInDoubt()
{
this.transaction.State.InDoubtFromDtc( this.transaction );
}
// Fanout Preprepare notifications
public override void Prepare( IPromotedEnlistment en )
{
this.preparingEnlistment = en;
PoolablePrepare( this );
}
public override void Commit( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableCommit( this );
}
public override void Rollback( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableRollback( this );
}
public override void InDoubt( IPromotedEnlistment en )
{
this.oletxEnlistment = en;
PoolableInDoubt( this );
}
}
internal struct VolatileEnlistmentSet
{
internal InternalEnlistment[] volatileEnlistments;
internal int volatileEnlistmentCount;
internal int volatileEnlistmentSize;
internal int dependentClones;
// Track the number of volatile enlistments that have prepared.
internal int preparedVolatileEnlistments;
// This is a single pinpoint enlistment to represent all volatile enlistments that
// may exist on a promoted transaction. This member should only be initialized if
// a transaction is promoted.
private VolatileDemultiplexer volatileDemux;
internal VolatileDemultiplexer VolatileDemux
{
get
{
return this.volatileDemux;
}
set
{
Debug.Assert( this.volatileDemux == null, "volatileDemux can only be set once." );
this.volatileDemux = value;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HtmlControlPersistable.cs
- FaultCode.cs
- OleAutBinder.cs
- StaticDataManager.cs
- ParameterCollection.cs
- sqlstateclientmanager.cs
- BitmapMetadataEnumerator.cs
- X509ChainElement.cs
- InsufficientExecutionStackException.cs
- TextPattern.cs
- WebBrowserEvent.cs
- ButtonDesigner.cs
- HttpCacheParams.cs
- OrderedEnumerableRowCollection.cs
- ChannelDispatcher.cs
- ClientBuildManager.cs
- SelectionHighlightInfo.cs
- WmlLinkAdapter.cs
- SafeHandles.cs
- jithelpers.cs
- ThrowOnMultipleAssignment.cs
- CodeAttributeArgument.cs
- AppDomainProtocolHandler.cs
- HistoryEventArgs.cs
- XhtmlBasicPageAdapter.cs
- SmiEventSink_DeferedProcessing.cs
- WindowsListViewItem.cs
- safelinkcollection.cs
- LayoutEvent.cs
- PenThread.cs
- BitmapEffectInputData.cs
- TableStyle.cs
- FlowDocumentPage.cs
- DragEventArgs.cs
- PermissionRequestEvidence.cs
- DropSource.cs
- ProcessModelSection.cs
- ProviderConnectionPoint.cs
- CachedTypeface.cs
- SemanticResolver.cs
- TransformPatternIdentifiers.cs
- Marshal.cs
- WSTrust.cs
- DesignerCategoryAttribute.cs
- ZoneButton.cs
- SystemUnicastIPAddressInformation.cs
- activationcontext.cs
- DefaultBinder.cs
- DbException.cs
- CommandSet.cs
- QilCloneVisitor.cs
- DrawTreeNodeEventArgs.cs
- Baml6ConstructorInfo.cs
- TagPrefixAttribute.cs
- SqlCacheDependencyDatabaseCollection.cs
- RoleGroup.cs
- IndentedTextWriter.cs
- MemoryPressure.cs
- WebBaseEventKeyComparer.cs
- EventNotify.cs
- LongValidatorAttribute.cs
- ApplicationServiceManager.cs
- TextCompositionManager.cs
- DataKeyCollection.cs
- BitmapImage.cs
- HttpSessionStateWrapper.cs
- HwndSubclass.cs
- TextEditorSpelling.cs
- AutoResetEvent.cs
- XmlSchemaSearchPattern.cs
- TreeNodeCollection.cs
- KnownTypes.cs
- COM2IVsPerPropertyBrowsingHandler.cs
- ExpressionTable.cs
- TextEditorParagraphs.cs
- IBuiltInEvidence.cs
- DocumentPageViewAutomationPeer.cs
- TimeoutValidationAttribute.cs
- PopupEventArgs.cs
- InstalledFontCollection.cs
- ApplicationSettingsBase.cs
- XmlLanguageConverter.cs
- AddressingVersion.cs
- InternalConfigEventArgs.cs
- DocumentPaginator.cs
- ValidationRule.cs
- ProcessDesigner.cs
- DoubleAnimationUsingPath.cs
- SecurityTokenAuthenticator.cs
- PersonalizationAdministration.cs
- XmlSchemaSimpleContent.cs
- WindowsImpersonationContext.cs
- ActiveXHost.cs
- QueryContinueDragEventArgs.cs
- MsmqBindingFilter.cs
- LinkGrep.cs
- CodeAttributeArgumentCollection.cs
- DbProviderServices.cs
- SafeTokenHandle.cs
- BitSet.cs