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; IDictionaryinstanceMetadataChanges; 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
- CachedBitmap.cs
- XmlUtil.cs
- DisplayMemberTemplateSelector.cs
- BackgroundWorker.cs
- LinqDataSourceHelper.cs
- AttachedPropertyBrowsableForChildrenAttribute.cs
- Ref.cs
- TableColumnCollectionInternal.cs
- DeflateStream.cs
- MetadataSection.cs
- dtdvalidator.cs
- ImageAnimator.cs
- BmpBitmapEncoder.cs
- OperatingSystemVersionCheck.cs
- BuilderInfo.cs
- Imaging.cs
- TdsEnums.cs
- TraceHandler.cs
- Resources.Designer.cs
- DummyDataSource.cs
- WebScriptEndpoint.cs
- DeviceContext2.cs
- DataTableReader.cs
- MessageDirection.cs
- DataTableCollection.cs
- SqlCommand.cs
- WebPartVerbCollection.cs
- InProcStateClientManager.cs
- HierarchicalDataBoundControl.cs
- ExpressionBuilder.cs
- StickyNote.cs
- ScriptingProfileServiceSection.cs
- WebServiceHostFactory.cs
- CodeActivityMetadata.cs
- coordinator.cs
- HttpResponseWrapper.cs
- ColorConverter.cs
- CommandTreeTypeHelper.cs
- DataGridViewLinkColumn.cs
- RoutedPropertyChangedEventArgs.cs
- DataGridViewSortCompareEventArgs.cs
- Debug.cs
- DataGridViewRowCancelEventArgs.cs
- ButtonBase.cs
- FtpWebRequest.cs
- ProviderConnectionPoint.cs
- DataSysAttribute.cs
- RtType.cs
- MenuItemBindingCollection.cs
- ThreadSafeList.cs
- ButtonChrome.cs
- XmlSchemaAll.cs
- PenLineCapValidation.cs
- AmbientLight.cs
- Types.cs
- TextEditorCopyPaste.cs
- ThemeDirectoryCompiler.cs
- CompressEmulationStream.cs
- graph.cs
- XmlParserContext.cs
- XmlAttributeCollection.cs
- XmlSchemaExporter.cs
- RtType.cs
- StorageEntitySetMapping.cs
- DashStyle.cs
- Annotation.cs
- RegionData.cs
- DropSource.cs
- GenericRootAutomationPeer.cs
- PathSegmentCollection.cs
- CodeDomSerializationProvider.cs
- RSAPKCS1SignatureDeformatter.cs
- FontSourceCollection.cs
- AnimationLayer.cs
- DrawingCollection.cs
- CodeAttachEventStatement.cs
- DataSpaceManager.cs
- EpmTargetPathSegment.cs
- HtmlShim.cs
- ErrorFormatterPage.cs
- ImmutableCollection.cs
- HttpContext.cs
- PowerModeChangedEventArgs.cs
- TypeUtil.cs
- Misc.cs
- LiteralTextParser.cs
- HttpHandlersSection.cs
- PackageDigitalSignature.cs
- ComplusTypeValidator.cs
- ElementProxy.cs
- WebPartHeaderCloseVerb.cs
- SqlWorkflowPersistenceService.cs
- RemotingService.cs
- TransformerInfoCollection.cs
- ExclusiveTcpListener.cs
- CellParagraph.cs
- assemblycache.cs
- BaseTemplateParser.cs
- XamlContextStack.cs
- TreeViewItemAutomationPeer.cs