Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / Dispatcher / DurableInstanceManager.cs / 1407647 / DurableInstanceManager.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------
namespace System.ServiceModel.Activities.Dispatcher
{
using System.Activities.DurableInstancing;
using System.Activities.Persistence;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime;
using System.Runtime.DurableInstancing;
using System.ServiceModel.Activities.Description;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Threading;
using System.Transactions;
using System.Xml.Linq;
using System.ServiceModel.Activation;
sealed class DurableInstanceManager
{
static AsyncCallback waitAndHandleStoreEventsCallback = Fx.ThunkCallback(new AsyncCallback(WaitAndHandleStoreEventsCallback));
int state;
InstanceStore store;
InstanceHandle handle;
InstanceOwner owner;
CreateWorkflowOwnerCommand createOwnerCommand;
object thisLock;
IDictionary instanceMetadataChanges;
AsyncWaitHandle waitForStoreEventsLoop;
internal DurableInstanceManager(WorkflowServiceHost host)
{
DurableInstancingOptions = new DurableInstancingOptions(this);
this.createOwnerCommand = new CreateWorkflowOwnerCommand();
this.instanceMetadataChanges = new Dictionary();
this.thisLock = new object();
// This is for collision detection. Will replace with the real service name prior to executing.
InstanceValue sentinel = new InstanceValue(XNamespace.Get("http://tempuri.org").GetName("Sentinel"));
this.createOwnerCommand.InstanceOwnerMetadata.Add(WorkflowNamespace.WorkflowHostType, sentinel);
this.instanceMetadataChanges.Add(WorkflowNamespace.WorkflowHostType, sentinel);
this.instanceMetadataChanges.Add(PersistenceMetadataNamespace.InstanceType, new InstanceValue(WorkflowNamespace.WorkflowHostType, InstanceValueOptions.WriteOnly));
this.Host = host;
}
WorkflowServiceHost Host { get; set; }
internal PersistenceProviderDirectory PersistenceProviderDirectory { get; set; }
public DurableInstancingOptions DurableInstancingOptions { get; private set; }
public InstanceStore InstanceStore
{
get
{
return this.store;
}
set
{
ThrowIfDisposedOrImmutable(this.state);
this.store = value;
}
}
public void AddInstanceOwnerValues(IDictionary readWriteValues, IDictionary writeOnlyValues)
{
ThrowIfDisposedOrImmutable(this.state);
if (readWriteValues != null)
{
foreach (KeyValuePair property in readWriteValues)
{
if (this.createOwnerCommand.InstanceOwnerMetadata.ContainsKey(property.Key))
{
throw FxTrace.Exception.Argument("readWriteValues", SR.ConflictingValueName(property.Key));
}
this.createOwnerCommand.InstanceOwnerMetadata.Add(property.Key, new InstanceValue(property.Value));
}
}
if (writeOnlyValues != null)
{
foreach (KeyValuePair property in writeOnlyValues)
{
if (this.createOwnerCommand.InstanceOwnerMetadata.ContainsKey(property.Key))
{
throw FxTrace.Exception.Argument("writeOnlyValues", SR.ConflictingValueName(property.Key));
}
this.createOwnerCommand.InstanceOwnerMetadata.Add(property.Key, new InstanceValue(property.Value,
InstanceValueOptions.Optional | InstanceValueOptions.WriteOnly));
}
}
}
public void AddInitialInstanceValues(IDictionary writeOnlyValues)
{
ThrowIfDisposedOrImmutable(this.state);
if (writeOnlyValues != null)
{
foreach (KeyValuePair pair in writeOnlyValues)
{
if (this.instanceMetadataChanges.ContainsKey(pair.Key))
{
throw FxTrace.Exception.Argument("writeOnlyValues", SR.ConflictingValueName(pair.Key));
}
this.instanceMetadataChanges.Add(pair.Key, new InstanceValue(pair.Value, InstanceValueOptions.Optional | InstanceValueOptions.WriteOnly));
}
}
}
static void ThrowIfDisposedOrImmutable(int state)
{
if (state == States.Aborted)
{
throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.ServiceHostExtensionAborted));
}
if (state == States.Closed)
{
throw FxTrace.Exception.AsError(new ObjectDisposedException(typeof(DurableInstanceManager).Name));
}
if (state == States.Opened)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ServiceHostExtensionImmutable));
}
}
static void ThrowIfClosedOrAborted(int state)
{
if (state == States.Aborted)
{
throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.ServiceHostExtensionAborted));
}
if (state == States.Closed)
{
throw FxTrace.Exception.AsError(new ObjectDisposedException(typeof(DurableInstanceManager).Name));
}
}
void InitializePersistenceProviderDirectory()
{
WorkflowServiceBehavior workflowServiceBehavior = Host.Description.Behaviors.Find();
Fx.Assert(workflowServiceBehavior != null, "WorkflowServiceBehavior must be present on WorkflowServiceHost.");
int maxInstances = ServiceThrottlingBehavior.DefaultMaxConcurrentInstances;
ServiceThrottlingBehavior serviceThrottlingBehavior = Host.Description.Behaviors.Find();
if (serviceThrottlingBehavior != null)
{
maxInstances = serviceThrottlingBehavior.MaxConcurrentInstances;
}
if (InstanceStore != null)
{
PersistenceProviderDirectory = new PersistenceProviderDirectory(InstanceStore, this.owner, this.instanceMetadataChanges, workflowServiceBehavior.Activity, Host, DurableConsistencyScope.Global, maxInstances);
}
else
{
PersistenceProviderDirectory = new PersistenceProviderDirectory(workflowServiceBehavior.Activity, Host, maxInstances);
}
bool aborted;
lock (this.thisLock)
{
aborted = this.state == States.Aborted;
}
if (aborted)
{
if (this.handle != null)
{
this.handle.Free();
}
PersistenceProviderDirectory.Abort();
}
// Start listening to store event
if (InstanceStore != null && !aborted)
{
this.waitForStoreEventsLoop = new AsyncWaitHandle(EventResetMode.ManualReset);
BeginWaitAndHandleStoreEvents(waitAndHandleStoreEventsCallback, this);
}
}
IAsyncResult BeginWaitAndHandleStoreEvents(AsyncCallback callback, object state)
{
return new WaitAndHandleStoreEventsAsyncResult(this, callback, state);
}
void EndWaitAndHandleStoreEvents(IAsyncResult result)
{
WaitAndHandleStoreEventsAsyncResult.End(result);
}
static void WaitAndHandleStoreEventsCallback(IAsyncResult result)
{
DurableInstanceManager thisPtr = (DurableInstanceManager)result.AsyncState;
bool stop = false;
try
{
thisPtr.EndWaitAndHandleStoreEvents(result);
}
catch (OperationCanceledException exception)
{
FxTrace.Exception.AsWarning(exception);
// The OCE, bubbled to this layer, is only from store.BeginWaitForEvents.
// This indicates handle is freed by 1) normal closing sequence 2) store
// is dead (eg. lock owner expired). We will fault the host as well as
// cease the loop.
if (thisPtr.Host.State == CommunicationState.Opening || thisPtr.Host.State == CommunicationState.Opened)
{
thisPtr.Host.Fault(exception);
}
stop = true;
}
catch (Exception exception)
{
if (Fx.IsFatal(exception) || !thisPtr.HandleException(exception))
{
throw;
}
}
// Continue
if (!stop && thisPtr.state == States.Opened)
{
thisPtr.BeginWaitAndHandleStoreEvents(waitAndHandleStoreEventsCallback, thisPtr);
}
else
{
thisPtr.waitForStoreEventsLoop.Set();
}
}
bool HandleException(Exception exception)
{
if (exception is TimeoutException ||
exception is OperationCanceledException ||
exception is TransactionException ||
exception is CommunicationObjectAbortedException ||
// When abort raised by WorkflowServiceInstance
exception is FaultException ||
exception is InstancePersistenceException)
{
FxTrace.Exception.AsWarning(exception);
this.Host.FaultServiceHostIfNecessary(exception);
return true;
}
return false;
}
void CheckPersistenceProviderBehavior()
{
foreach (IServiceBehavior behavior in Host.Description.Behaviors)
{
if (behavior.GetType().FullName == "System.ServiceModel.Description.PersistenceProviderBehavior")
{
throw FxTrace.Exception.AsError(new CommunicationException(SR.UseInstanceStoreInsteadOfPersistenceProvider));
}
}
}
internal IAsyncResult BeginGetInstance(InstanceKey instanceKey, ICollection additionalKeys, WorkflowGetInstanceContext parameters, TimeSpan timeout, AsyncCallback callback, object state)
{
ThrowIfClosedOrAborted(this.state);
return new GetInstanceAsyncResult(this, instanceKey, additionalKeys, parameters, timeout, callback, state);
}
internal IAsyncResult BeginGetInstance(Guid instanceId, WorkflowGetInstanceContext parameters,
TimeSpan timeout, AsyncCallback callback, object state)
{
ThrowIfClosedOrAborted(this.state);
return new GetInstanceAsyncResult(this, instanceId, parameters, timeout, callback, state);
}
internal WorkflowServiceInstance EndGetInstance(IAsyncResult result)
{
return GetInstanceAsyncResult.End(result);
}
void AbortDirectory()
{
lock (this.thisLock)
{
if (this.state == States.Aborted)
{
return;
}
this.state = States.Aborted;
}
if (this.handle != null)
{
this.handle.Free();
}
// PersistenceProviderDirectory is assigned on opened. Abort could happen before (eg. after created)
if (PersistenceProviderDirectory != null)
{
PersistenceProviderDirectory.Abort();
}
}
void SetDefaultOwnerMetadata()
{
// Replace the sentinal value with the real scoping name here.
this.createOwnerCommand.InstanceOwnerMetadata[WorkflowNamespace.WorkflowHostType] = new InstanceValue(Host.DurableInstancingOptions.ScopeName);
this.instanceMetadataChanges[WorkflowNamespace.WorkflowHostType] = new InstanceValue(Host.DurableInstancingOptions.ScopeName);
if (!this.instanceMetadataChanges.ContainsKey(WorkflowServiceNamespace.Service))
{
this.instanceMetadataChanges[WorkflowServiceNamespace.Service] = new InstanceValue(Host.ServiceName, InstanceValueOptions.WriteOnly | InstanceValueOptions.Optional);
}
// add instance metadata about all of our endpoints
foreach (ServiceEndpoint endpoint in this.Host.Description.Endpoints)
{
if (endpoint.Name != null)
{
// treat the control endpoint as special
if (endpoint is WorkflowControlEndpoint)
{
if (!this.createOwnerCommand.InstanceOwnerMetadata.ContainsKey(WorkflowServiceNamespace.ControlEndpoint))
{
this.createOwnerCommand.InstanceOwnerMetadata.Add(WorkflowServiceNamespace.ControlEndpoint, new InstanceValue(endpoint.ListenUri));
}
}
else
{
XName endpointName = WorkflowServiceNamespace.EndpointsPath.GetName(endpoint.Name);
if (!this.createOwnerCommand.InstanceOwnerMetadata.ContainsKey(endpointName))
{
this.createOwnerCommand.InstanceOwnerMetadata.Add(endpointName, new InstanceValue(endpoint.ListenUri));
}
}
}
}
// as well as additional metadata if we're hosted
VirtualPathExtension virtualPathExtension = this.Host.Extensions.Find();
if (virtualPathExtension != null && !this.instanceMetadataChanges.ContainsKey(PersistenceMetadataNamespace.ActivationType))
{
// Example values for various web-host properties
// SiteName: "Default Website"
// RelativeApplicationPath/ApplicationVirtualPath: "/myApp1"
// Virtual Path: "~/ShoppingCartService/ShoppingCartService.xaml"
// Relative Service Path: "/myApp1/ShoppingCartService/ShoppingCartService.xaml"
this.instanceMetadataChanges.Add(PersistenceMetadataNamespace.ActivationType, new InstanceValue(PersistenceMetadataNamespace.ActivationTypes.WAS, InstanceValueOptions.WriteOnly | InstanceValueOptions.Optional));
// The remaining properties will get overritten if the user set them manually. To control activation, the user should also set ActivationType, even if just to WAS.
this.instanceMetadataChanges[WorkflowServiceNamespace.SiteName] = new InstanceValue(virtualPathExtension.SiteName, InstanceValueOptions.WriteOnly | InstanceValueOptions.Optional);
this.instanceMetadataChanges[WorkflowServiceNamespace.RelativeApplicationPath] = new InstanceValue(virtualPathExtension.ApplicationVirtualPath, InstanceValueOptions.WriteOnly | InstanceValueOptions.Optional);
string virtualPath = virtualPathExtension.VirtualPath.Substring(1);
string relativePath = ("/" == virtualPathExtension.ApplicationVirtualPath) ? virtualPath : virtualPathExtension.ApplicationVirtualPath + virtualPath;
this.instanceMetadataChanges[WorkflowServiceNamespace.RelativeServicePath] = new InstanceValue(relativePath, InstanceValueOptions.WriteOnly | InstanceValueOptions.Optional);
}
}
public void Open(TimeSpan timeout)
{
Fx.Assert(Host != null, "Extension should have been attached in WorkflowServiceHost constructor.");
lock (this.thisLock)
{
ThrowIfDisposedOrImmutable(this.state);
this.state = States.Opened;
}
CheckPersistenceProviderBehavior();
SetDefaultOwnerMetadata();
if (InstanceStore != null)
{
using (new TransactionScope(TransactionScopeOption.Suppress))
{
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
InstanceHandle handle = null;
try
{
handle = InstanceStore.CreateInstanceHandle(null);
this.owner = InstanceStore.Execute(handle, this.createOwnerCommand, timeoutHelper.RemainingTime()).InstanceOwner;
this.handle = handle;
handle = null;
}
catch (InstancePersistenceException exception)
{
throw FxTrace.Exception.AsError(new CommunicationException(SR.UnableToOpenAndRegisterStore, exception));
}
finally
{
if (handle != null)
{
handle.Free();
}
}
}
}
InitializePersistenceProviderDirectory();
}
public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
{
Fx.Assert(Host != null, "Extension should have been attached in WorkflowServiceHost constructor.");
using (new TransactionScope(TransactionScopeOption.Suppress))
{
return new OpenInstanceStoreAsyncResult(this, timeout, callback, state);
}
}
public void EndOpen(IAsyncResult result)
{
OpenInstanceStoreAsyncResult.End(result);
}
public void Close(TimeSpan timeout)
{
// We normally would have a purely synchronous path for our synchronous
// overload, but PersistenceIOParticipant.OnBeginSave() doesn't have a synchronous counterpart.
// Given that, at the very least we'd have to do PersistencePipeline.EndSave(PersistencePipeline.BeginSave).
// Therefore we resign ourselves to End(Begin) and take comfort in the unification of logic by not having two codepaths
CloseAsyncResult.End(new CloseAsyncResult(this, timeout, null, null));
}
public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
{
return new CloseAsyncResult(this, timeout, callback, state);
}
public void EndClose(IAsyncResult result)
{
CloseAsyncResult.End(result);
}
public void Abort()
{
AbortDirectory();
}
static class States
{
public const int Created = 0;
public const int Opened = 1;
public const int Closed = 2;
public const int Aborted = 3;
}
class OpenInstanceStoreAsyncResult : AsyncResult
{
static AsyncCompletion handleEndExecute = new AsyncCompletion(HandleEndExecute);
static Action onFinally = new Action(OnFinally);
DurableInstanceManager instanceManager;
TimeoutHelper timeoutHelper;
InstanceHandle handle;
public OpenInstanceStoreAsyncResult(DurableInstanceManager instanceManager, TimeSpan timeout, AsyncCallback callback, object state)
: base(callback, state)
{
this.instanceManager = instanceManager;
this.timeoutHelper = new TimeoutHelper(timeout);
lock (this.instanceManager.thisLock)
{
DurableInstanceManager.ThrowIfDisposedOrImmutable(this.instanceManager.state);
this.instanceManager.state = States.Opened;
}
instanceManager.CheckPersistenceProviderBehavior();
this.instanceManager.SetDefaultOwnerMetadata();
this.OnCompleting = OpenInstanceStoreAsyncResult.onFinally;
bool completeSelf;
Exception completionException = null;
try
{
if (instanceManager.InstanceStore == null)
{
completeSelf = CreateDirectory();
}
else
{
this.handle = this.instanceManager.InstanceStore.CreateInstanceHandle(null);
IAsyncResult executeResult = this.instanceManager.InstanceStore.BeginExecute(this.handle,
this.instanceManager.createOwnerCommand, this.timeoutHelper.RemainingTime(),
this.PrepareAsyncCompletion(OpenInstanceStoreAsyncResult.handleEndExecute), this);
completeSelf = SyncContinue(executeResult);
}
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
completionException = exception;
completeSelf = true;
}
if (completeSelf)
{
Complete(true, completionException);
}
}
static bool HandleEndExecute(IAsyncResult result)
{
OpenInstanceStoreAsyncResult thisPtr = (OpenInstanceStoreAsyncResult)result.AsyncState;
thisPtr.instanceManager.owner = thisPtr.instanceManager.InstanceStore.EndExecute(result).InstanceOwner;
return thisPtr.CreateDirectory();
}
static void OnFinally(AsyncResult result, Exception exception)
{
if (exception != null)
{
try
{
if (exception is InstancePersistenceException)
{
throw FxTrace.Exception.AsError(new CommunicationException(SR.UnableToOpenAndRegisterStore, exception));
}
}
finally
{
OpenInstanceStoreAsyncResult thisPtr = (OpenInstanceStoreAsyncResult)result;
if (thisPtr.handle != null)
{
thisPtr.handle.Free();
}
}
}
}
public static void End(IAsyncResult result)
{
AsyncResult.End(result);
}
bool CreateDirectory()
{
this.instanceManager.InitializePersistenceProviderDirectory();
this.instanceManager.handle = this.handle;
this.handle = null;
return true;
}
}
class CloseAsyncResult : AsyncResult
{
static AsyncCompletion handleEndReleaseInstance = new AsyncCompletion(HandleEndReleaseInstance);
static AsyncCompletion handleEndExecute = new AsyncCompletion(HandleEndExecute);
static Action
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ServiceDurableInstance.cs
- MethodBuilderInstantiation.cs
- DateTimeOffsetStorage.cs
- webproxy.cs
- _IPv6Address.cs
- QueryCacheManager.cs
- ExecutionEngineException.cs
- RangeValueProviderWrapper.cs
- InvalidCastException.cs
- ViewManager.cs
- SqlVersion.cs
- DataPager.cs
- BufferBuilder.cs
- AssemblyCache.cs
- ResourcesChangeInfo.cs
- XmlAttributeProperties.cs
- SetterBaseCollection.cs
- OleDbPermission.cs
- FormsIdentity.cs
- StrokeCollection.cs
- PeerApplicationLaunchInfo.cs
- BufferedStream2.cs
- RoleGroup.cs
- ForeignKeyConstraint.cs
- StreamGeometry.cs
- TypefaceMap.cs
- COM2IProvidePropertyBuilderHandler.cs
- PropertyGrid.cs
- HostProtectionPermission.cs
- WebPartExportVerb.cs
- XmlSchemaValidationException.cs
- TileBrush.cs
- RoleService.cs
- Cursor.cs
- UnknownExceptionActionHelper.cs
- SequentialUshortCollection.cs
- AutomationPropertyInfo.cs
- OLEDB_Enum.cs
- SystemIPAddressInformation.cs
- SizeAnimationClockResource.cs
- DataControlPagerLinkButton.cs
- ButtonFieldBase.cs
- AlternateViewCollection.cs
- AdapterDictionary.cs
- TextSelectionHighlightLayer.cs
- RotateTransform3D.cs
- StandardRuntimeEnumValidatorAttribute.cs
- DiffuseMaterial.cs
- ListItemParagraph.cs
- ACE.cs
- TreeView.cs
- PasswordTextContainer.cs
- SafeBitVector32.cs
- invalidudtexception.cs
- ClipboardProcessor.cs
- EncoderFallback.cs
- MD5CryptoServiceProvider.cs
- Native.cs
- ParenthesizePropertyNameAttribute.cs
- WeakEventTable.cs
- NoResizeHandleGlyph.cs
- TemplateContainer.cs
- ExpressionParser.cs
- X509SecurityToken.cs
- StylusPlugin.cs
- TextUtf8RawTextWriter.cs
- ConstantCheck.cs
- CroppedBitmap.cs
- RuntimeHelpers.cs
- RegexRunnerFactory.cs
- DeclarativeCatalogPart.cs
- ZipIOExtraFieldZip64Element.cs
- DataGridSortCommandEventArgs.cs
- ChineseLunisolarCalendar.cs
- glyphs.cs
- ProfessionalColorTable.cs
- ExceptionValidationRule.cs
- StyleXamlTreeBuilder.cs
- MetaModel.cs
- EnumBuilder.cs
- HttpProfileGroupBase.cs
- ThreadAbortException.cs
- OdbcError.cs
- FilteredReadOnlyMetadataCollection.cs
- SqlDataReaderSmi.cs
- __Filters.cs
- QueryStringConverter.cs
- DrawTreeNodeEventArgs.cs
- CustomError.cs
- EventRecordWrittenEventArgs.cs
- MinimizableAttributeTypeConverter.cs
- InlineCollection.cs
- EdmEntityTypeAttribute.cs
- CompiledXpathExpr.cs
- dsa.cs
- HostedAspNetEnvironment.cs
- EntityDataSourceColumn.cs
- SqlClientFactory.cs
- DefaultAsyncDataDispatcher.cs
- ValidationErrorInfo.cs