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
- CodeAssignStatement.cs
- ErrorTolerantObjectWriter.cs
- NativeMethods.cs
- SqlCacheDependencyDatabase.cs
- XmlSchemaAttribute.cs
- InternalControlCollection.cs
- UnsafeNativeMethods.cs
- NavigationCommands.cs
- FloatAverageAggregationOperator.cs
- InternalPermissions.cs
- _IPv4Address.cs
- PointConverter.cs
- XmlNodeWriter.cs
- NumericPagerField.cs
- ItemList.cs
- WorkflowPersistenceService.cs
- TreeViewHitTestInfo.cs
- NamespaceDisplayAutomationPeer.cs
- AlternateView.cs
- ScriptResourceAttribute.cs
- wmiprovider.cs
- ConnectionsZoneDesigner.cs
- DataSourceSerializationException.cs
- thaishape.cs
- ExpressionServices.cs
- XmlNodeReader.cs
- AudioLevelUpdatedEventArgs.cs
- XPathDescendantIterator.cs
- GatewayIPAddressInformationCollection.cs
- ClientScriptItem.cs
- TemplateBindingExpressionConverter.cs
- COM2Properties.cs
- SqlMetaData.cs
- SizeConverter.cs
- DoubleCollectionConverter.cs
- CodeDirectionExpression.cs
- XmlSchemaExporter.cs
- EncryptedData.cs
- AutoSizeToolBoxItem.cs
- StructureChangedEventArgs.cs
- RoleManagerModule.cs
- ObsoleteAttribute.cs
- CookielessHelper.cs
- XmlSerializerImportOptions.cs
- CellIdBoolean.cs
- IISMapPath.cs
- TreeNode.cs
- MouseGestureValueSerializer.cs
- CommandID.cs
- EntitySetBaseCollection.cs
- ConfigViewGenerator.cs
- TreeNodeBindingCollection.cs
- PersistenceProviderElement.cs
- SqlClientFactory.cs
- ISFTagAndGuidCache.cs
- PasswordRecovery.cs
- WebPartMovingEventArgs.cs
- PassportIdentity.cs
- AssemblyBuilderData.cs
- EmptyEnumerable.cs
- HttpProtocolReflector.cs
- WmlCalendarAdapter.cs
- CollectionBase.cs
- CLRBindingWorker.cs
- CryptographicAttribute.cs
- SiteMapNodeItemEventArgs.cs
- WebControlsSection.cs
- Win32.cs
- RegexWorker.cs
- CodeParameterDeclarationExpressionCollection.cs
- HttpApplicationFactory.cs
- DataGridViewRow.cs
- FontConverter.cs
- ColorConverter.cs
- ThumbAutomationPeer.cs
- SqlCacheDependency.cs
- SQLByte.cs
- VerificationException.cs
- CodeSubDirectoriesCollection.cs
- SerialReceived.cs
- EncoderExceptionFallback.cs
- MDIClient.cs
- TimelineClockCollection.cs
- TypedDataSetSchemaImporterExtension.cs
- RouteParametersHelper.cs
- baseaxisquery.cs
- EncoderExceptionFallback.cs
- PathSegmentCollection.cs
- PerformanceCounter.cs
- PersonalizationStateQuery.cs
- RestHandler.cs
- DBAsyncResult.cs
- ImageCodecInfo.cs
- XmlSchemaComplexType.cs
- UrlMappingsSection.cs
- XmlBaseWriter.cs
- AspNetSynchronizationContext.cs
- CompilationUnit.cs
- UserPreferenceChangingEventArgs.cs
- SpanIndex.cs