Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx35 / System.WorkflowServices / System / ServiceModel / Dispatcher / DurableInstanceContextProvider.cs / 1305376 / DurableInstanceContextProvider.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Dispatcher { using System.Collections.Generic; using System.Runtime; using System.Runtime.Diagnostics; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Diagnostics; using System.Threading; using System.Diagnostics; abstract class DurableInstanceContextProvider : IInstanceContextProvider { ContextCache contextCache; bool isPerCall; ServiceHostBase serviceHostBase; protected DurableInstanceContextProvider(ServiceHostBase serviceHostBase, bool isPerCall) { if (serviceHostBase == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceHostBase"); } this.serviceHostBase = serviceHostBase; if (serviceHostBase.Description.Behaviors.Find() == null) { serviceHostBase.ServiceThrottle.MaxConcurrentInstances = (new ServiceThrottlingBehavior()).MaxConcurrentInstances; } this.contextCache = new ContextCache(); this.isPerCall = isPerCall; } protected ContextCache Cache { get { return this.contextCache; } } public virtual InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel) { if (message == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); } if (channel == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channel"); } Guid instanceId = GetInstanceIdFromMessage(message); InstanceContext result = null; if (instanceId != Guid.Empty) //Not an activation request. { if (contextCache.TryGetInstanceContext(instanceId, out result)) { lock (result.ThisLock) { if (!string.IsNullOrEmpty(channel.SessionId) && !result.IncomingChannels.Contains(channel)) { result.IncomingChannels.Add(channel); } } return result; } } return result; } public int GetReferenceCount(Guid instanceId) { return this.Cache.GetReferenceCount(instanceId); } public virtual void InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel) { if (instanceContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instanceContext"); } if (message == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message"); } if (channel == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channel"); } Guid instanceId = GetInstanceIdFromMessage(message); DurableInstance durableInstance; if (instanceId == Guid.Empty) //Activation Request. { instanceId = Guid.NewGuid(); durableInstance = this.OnCreateNewInstance(instanceId); message.Properties[DurableMessageDispatchInspector.NewDurableInstanceIdPropertyName] = instanceId; } else { durableInstance = this.OnGetExistingInstance(instanceId); } Fx.Assert(durableInstance != null, "Durable instance should never be null at this point."); durableInstance.Open(); instanceContext.Extensions.Add(durableInstance); if (!string.IsNullOrEmpty(channel.SessionId)) { instanceContext.IncomingChannels.Add(channel); } contextCache.AddInstanceContext(instanceId, instanceContext); if (DiagnosticUtility.ShouldTraceInformation) { string traceText = SR.GetString(SR.TraceCodeDICPInstanceContextCached, instanceId); TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.DICPInstanceContextCached, SR.GetString(SR.TraceCodeDICPInstanceContextCached), new StringTraceRecord("InstanceDetail", traceText), this, null); } } public virtual bool IsIdle(InstanceContext instanceContext) { bool removed = false; if (instanceContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instanceContext"); } DurableInstance durableInstance = instanceContext.Extensions.Find (); if (durableInstance == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR2.GetString( SR2.RequiredInstanceContextExtensionNotFound, typeof(DurableInstance).Name))); } lock (instanceContext.ThisLock) { if (instanceContext.IncomingChannels.Count == 0) { removed = contextCache.RemoveIfNotBusy(durableInstance.InstanceId, instanceContext); } } if (removed && DiagnosticUtility.ShouldTraceInformation) { string traceText = SR.GetString(SR.TraceCodeDICPInstanceContextRemovedFromCache, durableInstance.InstanceId); TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.DICPInstanceContextRemovedFromCache, SR.GetString(SR.TraceCodeDICPInstanceContextRemovedFromCache), new StringTraceRecord("InstanceDetail", traceText), this, null); } return removed; } public virtual void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext) { } //Called by MessageInspector.BeforeReply internal void DecrementActivityCount(Guid instanceId) { contextCache.ReleaseReference(instanceId); } internal void UnbindAbortedInstance(InstanceContext instanceContext, Guid instanceId) { if (instanceContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instanceContext"); } //We made our best effor to clean up the instancecontext out of our cache. //If another request already in middle of processing the request on InstanceContext //It will Fail with CommunicationException. this.contextCache.Remove(instanceId, instanceContext); } protected virtual Guid GetInstanceIdFromMessage(Message message) { if (!this.isPerCall) { ContextMessageProperty contextProperties = null; string instanceId = null; if (ContextMessageProperty.TryGet(message, out contextProperties)) { if (contextProperties.Context.TryGetValue(WellKnownContextProperties.InstanceId, out instanceId)) { return Fx.CreateGuid(instanceId); } } } return Guid.Empty; } protected abstract DurableInstance OnCreateNewInstance(Guid instanceId); protected abstract DurableInstance OnGetExistingInstance(Guid instanceId); //This class takes self contained lock, never calls out with lock taken. protected class ContextCache { Dictionary contextCache; object lockObject = new object(); public ContextCache() { contextCache = new Dictionary (); } public void AddInstanceContext(Guid instanceId, InstanceContext instanceContext) { ContextItem contextItem; int? referenceCount = null; lock (lockObject) { if (!contextCache.TryGetValue(instanceId, out contextItem)) { //This will be the case for activation request. contextItem = new ContextItem(instanceId); referenceCount = contextItem.AddReference(); contextCache.Add(instanceId, contextItem); } } contextItem.InstanceContext = instanceContext; if (DiagnosticUtility.ShouldTraceInformation && referenceCount.HasValue) { string traceText = SR2.GetString(SR2.DurableInstanceRefCountToInstanceContext, instanceId, referenceCount.Value); TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.InstanceContextBoundToDurableInstance, SR.GetString(SR.TraceCodeInstanceContextBoundToDurableInstance), new StringTraceRecord("InstanceDetail", traceText), this, null); } } public bool Contains(Guid instanceId, InstanceContext instanceContext) { ContextItem contextItem = null; lock (this.lockObject) { if (contextCache.TryGetValue(instanceId, out contextItem)) { return object.ReferenceEquals(contextItem.InstanceContext, instanceContext); } return false; } } public int GetReferenceCount(Guid instanceId) { int result = 0; lock (lockObject) { ContextItem contextItem; if (contextCache.TryGetValue(instanceId, out contextItem)) { result = contextItem.ReferenceCount; } } return result; } public void ReleaseReference(Guid instanceId) { int referenceCount = -1; ContextItem contextItem; lock (lockObject) { if (contextCache.TryGetValue(instanceId, out contextItem)) { referenceCount = contextItem.ReleaseReference(); } else { Fx.Assert(false, "Cannot Release Reference of non exisiting items"); } } if (DiagnosticUtility.ShouldTraceInformation) { string traceText = SR2.GetString(SR2.DurableInstanceRefCountToInstanceContext, instanceId, referenceCount); TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.InstanceContextDetachedFromDurableInstance, SR.GetString(SR.TraceCodeInstanceContextDetachedFromDurableInstance), new StringTraceRecord("InstanceDetail", traceText), this, null); } } public bool Remove(Guid instanceId, InstanceContext instanceContext) { lock (this.lockObject) { ContextItem contextItem = null; if (this.contextCache.TryGetValue(instanceId, out contextItem)) { if (object.ReferenceEquals(instanceContext, contextItem.InstanceContext)) { return this.contextCache.Remove(instanceId); } } //InstanceContext is not in memory. return false; } } public bool RemoveIfNotBusy(Guid instanceId, InstanceContext instanceContext) { lock (lockObject) { ContextItem contextItem = null; if (contextCache.TryGetValue(instanceId, out contextItem)) { if (object.ReferenceEquals(contextItem.InstanceContext, instanceContext)) { return (!contextItem.HasOutstandingReference) && (contextCache.Remove(instanceId)); } } //InstanceContext is not in memory. return true; } } //Helper method to call from GetExistingInstanceContext //returns true : If InstanceContext is found in cache & guaranteed to stay in cache until ReleaseReference is called. //returns false : If InstanceContext is not found in cache; // reference & slot is created for the ID; // InitializeInstanceContext to call AddInstanceContext. public bool TryGetInstanceContext(Guid instanceId, out InstanceContext instanceContext) { ContextItem contextItem; instanceContext = null; int referenceCount = -1; try { lock (lockObject) { if (!contextCache.TryGetValue(instanceId, out contextItem)) { contextItem = new ContextItem(instanceId); referenceCount = contextItem.AddReference(); contextCache.Add(instanceId, contextItem); return false; } referenceCount = contextItem.AddReference(); } } finally { if (DiagnosticUtility.ShouldTraceInformation) { string traceText = SR2.GetString(SR2.DurableInstanceRefCountToInstanceContext, instanceId, referenceCount); TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.InstanceContextBoundToDurableInstance, SR.GetString(SR.TraceCodeInstanceContextBoundToDurableInstance), new StringTraceRecord("InstanceDetail", traceText), this, null); } } instanceContext = contextItem.InstanceContext; return true; } class ContextItem { InstanceContext context; Guid instanceId; object lockObject; int referenceCount; public ContextItem(Guid instanceId) { lockObject = new object(); referenceCount = 0; this.instanceId = instanceId; } public bool HasOutstandingReference { get { return this.referenceCount > 0; } } public InstanceContext InstanceContext { get { if (this.context == null) { lock (this.lockObject) { if (this.context == null) { Monitor.Wait(this.lockObject); } } } Fx.Assert(this.context != null, "Context cannot be null at this point"); return this.context; } set { if (value == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); } this.context = value; lock (this.lockObject) { Monitor.PulseAll(this.lockObject); } } } public int ReferenceCount { get { return this.referenceCount; } } public int AddReference() { //Called from higher locks taken return ++this.referenceCount; } public int ReleaseReference() { Fx.Assert(referenceCount > 0, "Reference count gone to negative"); //Called from higher locks taken return --this.referenceCount; } } } } } // 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
- FileSystemWatcher.cs
- XPathCompileException.cs
- RichTextBox.cs
- Cloud.cs
- TransportListener.cs
- ConnectionString.cs
- DefaultHttpHandler.cs
- TreeViewBindingsEditor.cs
- DataSourceControl.cs
- StylusSystemGestureEventArgs.cs
- FontStyle.cs
- UseManagedPresentationBindingElementImporter.cs
- LexicalChunk.cs
- SystemIPGlobalProperties.cs
- XmlSecureResolver.cs
- XmlnsCache.cs
- EntityDataSourceStatementEditor.cs
- PackWebResponse.cs
- TemplateContent.cs
- PropertyTabAttribute.cs
- XmlNullResolver.cs
- CodeExpressionCollection.cs
- DataList.cs
- WsatTransactionHeader.cs
- IntegerValidatorAttribute.cs
- StaticResourceExtension.cs
- GenericIdentity.cs
- XPathLexer.cs
- UnmanagedMarshal.cs
- GatewayIPAddressInformationCollection.cs
- ProfileServiceManager.cs
- RefType.cs
- Tablet.cs
- CatalogPartDesigner.cs
- Delay.cs
- BamlBinaryWriter.cs
- DesignerExtenders.cs
- DataServiceRequest.cs
- QueryableDataSource.cs
- PageResolution.cs
- TextServicesPropertyRanges.cs
- MobileSysDescriptionAttribute.cs
- BitmapEffectState.cs
- DataGridViewTextBoxColumn.cs
- _OverlappedAsyncResult.cs
- ApplicationInfo.cs
- ToolBarDesigner.cs
- ThumbButtonInfo.cs
- DataServiceStreamProviderWrapper.cs
- Module.cs
- SpnEndpointIdentity.cs
- IPEndPoint.cs
- IssuanceTokenProviderBase.cs
- ThreadAttributes.cs
- ReadOnlyNameValueCollection.cs
- QuaternionConverter.cs
- Focus.cs
- AutomationElement.cs
- BamlStream.cs
- DynamicRendererThreadManager.cs
- ComPlusTypeLoader.cs
- TrackingStringDictionary.cs
- SignerInfo.cs
- ViewCellSlot.cs
- ClientSettingsProvider.cs
- DesignerTransactionCloseEvent.cs
- ToolbarAUtomationPeer.cs
- ReadOnlyActivityGlyph.cs
- UIElementParaClient.cs
- PeerCollaborationPermission.cs
- SystemIPInterfaceProperties.cs
- ContainerSelectorBehavior.cs
- ClientOptions.cs
- GeneratedCodeAttribute.cs
- GenericIdentity.cs
- MsmqPoisonMessageException.cs
- DesignerDataSourceView.cs
- WriteableBitmap.cs
- SchemaCollectionPreprocessor.cs
- Wizard.cs
- MemberAssignment.cs
- ScriptComponentDescriptor.cs
- EditingCommands.cs
- SqlDataSourceEnumerator.cs
- CapiSymmetricAlgorithm.cs
- SponsorHelper.cs
- GPRECT.cs
- JsonStringDataContract.cs
- PersonalizationStateInfoCollection.cs
- Privilege.cs
- SharedStatics.cs
- AppDomainProtocolHandler.cs
- ApplicationException.cs
- ipaddressinformationcollection.cs
- Transform3DGroup.cs
- SqlCommandSet.cs
- ConfigXmlAttribute.cs
- MouseGestureValueSerializer.cs
- TypeGeneratedEventArgs.cs
- AuthenticationServiceManager.cs