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
- Version.cs
- UiaCoreProviderApi.cs
- ServiceNotStartedException.cs
- NTAccount.cs
- MessageDescriptionCollection.cs
- JpegBitmapDecoder.cs
- HttpServerUtilityWrapper.cs
- DataBindingCollectionEditor.cs
- AspNetSynchronizationContext.cs
- DockingAttribute.cs
- BindMarkupExtensionSerializer.cs
- DeviceContext2.cs
- ReachDocumentPageSerializerAsync.cs
- CodeTypeDelegate.cs
- SEHException.cs
- ZipIOLocalFileHeader.cs
- AsmxEndpointPickerExtension.cs
- FixedSOMElement.cs
- XhtmlTextWriter.cs
- AutomationPatternInfo.cs
- Expression.cs
- ToolStripItemImageRenderEventArgs.cs
- StorageSetMapping.cs
- SimpleExpression.cs
- JsonXmlDataContract.cs
- Int32CAMarshaler.cs
- HttpCookieCollection.cs
- NativeMethods.cs
- WinEventHandler.cs
- EventDescriptor.cs
- EventLogRecord.cs
- DetailsViewDeletedEventArgs.cs
- BindingCollection.cs
- WriterOutput.cs
- BindingCompleteEventArgs.cs
- DispatcherFrame.cs
- QueueProcessor.cs
- DefaultPrintController.cs
- DatagridviewDisplayedBandsData.cs
- TabletDevice.cs
- XmlArrayAttribute.cs
- BitmapSourceSafeMILHandle.cs
- TypeDelegator.cs
- OracleConnectionString.cs
- SizeFConverter.cs
- CustomCategoryAttribute.cs
- BindingExpressionUncommonField.cs
- WindowsFormsHost.cs
- BrowserCapabilitiesFactoryBase.cs
- HtmlToClrEventProxy.cs
- RectangleConverter.cs
- RequestQueryProcessor.cs
- Application.cs
- NameValueSectionHandler.cs
- RawStylusInputCustomData.cs
- EntityParameter.cs
- TextEffect.cs
- EntryWrittenEventArgs.cs
- ColorIndependentAnimationStorage.cs
- ServerType.cs
- DataGridHelper.cs
- OdbcUtils.cs
- MultiBindingExpression.cs
- BindingOperations.cs
- UpdatePanel.cs
- InkCanvasFeedbackAdorner.cs
- Slider.cs
- MediaPlayer.cs
- SecureEnvironment.cs
- wgx_exports.cs
- SafeMemoryMappedFileHandle.cs
- CodeObject.cs
- PolicyLevel.cs
- PagerSettings.cs
- RequiredAttributeAttribute.cs
- RegexRunnerFactory.cs
- ValidationSummary.cs
- X509ChainPolicy.cs
- ModelItemExtensions.cs
- CultureTable.cs
- StructuralComparisons.cs
- FileInfo.cs
- SecurityTokenException.cs
- ClientRuntimeConfig.cs
- CollectionConverter.cs
- Lease.cs
- LinqDataSourceHelper.cs
- ExcludePathInfo.cs
- PointLightBase.cs
- RubberbandSelector.cs
- DesignerCommandAdapter.cs
- AmbientLight.cs
- StrokeIntersection.cs
- XmlWrappingWriter.cs
- UniqueIdentifierService.cs
- XmlSchemaCollection.cs
- AgileSafeNativeMemoryHandle.cs
- documentsequencetextcontainer.cs
- MenuItemBinding.cs
- ContractBase.cs