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
- Item.cs
- ObjectItemLoadingSessionData.cs
- KnownBoxes.cs
- PropertyTabAttribute.cs
- LoggedException.cs
- SrgsElementFactory.cs
- XsltException.cs
- SQLResource.cs
- WebPartsSection.cs
- SettingsProperty.cs
- IteratorFilter.cs
- PasswordRecovery.cs
- BufferModeSettings.cs
- MaskedTextBoxDesigner.cs
- DoWorkEventArgs.cs
- MsmqIntegrationBindingElement.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- Fx.cs
- ImplicitInputBrush.cs
- Triplet.cs
- DataGridViewHeaderCell.cs
- ToolStripItemRenderEventArgs.cs
- StylusShape.cs
- LogicalExpressionEditor.cs
- ObjectToken.cs
- ConnectionManagementElementCollection.cs
- CompilerErrorCollection.cs
- AutomationProperties.cs
- FreezableCollection.cs
- MimePart.cs
- ParallelQuery.cs
- XPathNodeInfoAtom.cs
- Select.cs
- TextProperties.cs
- BitConverter.cs
- PersonalizablePropertyEntry.cs
- ExtendedProtectionPolicyElement.cs
- ItemCheckEvent.cs
- EntityClientCacheEntry.cs
- bidPrivateBase.cs
- AsyncPostBackErrorEventArgs.cs
- RegexParser.cs
- TextAdaptor.cs
- WebControlAdapter.cs
- TryCatchDesigner.xaml.cs
- _StreamFramer.cs
- CallContext.cs
- DataGridCheckBoxColumn.cs
- ProxyHwnd.cs
- ServiceOperationViewControl.cs
- UnrecognizedAssertionsBindingElement.cs
- VirtualPath.cs
- ComponentCommands.cs
- EnvelopedPkcs7.cs
- DrawingDrawingContext.cs
- DataGridViewControlCollection.cs
- SystemResourceKey.cs
- Int32Converter.cs
- ImportCatalogPart.cs
- SystemResources.cs
- AppSettingsExpressionBuilder.cs
- BamlTreeMap.cs
- TripleDESCryptoServiceProvider.cs
- CodeExpressionCollection.cs
- DefaultClaimSet.cs
- XmlEncodedRawTextWriter.cs
- ReadOnlyPropertyMetadata.cs
- HtmlMeta.cs
- ComplexLine.cs
- Int32.cs
- DataGridViewImageColumn.cs
- MdImport.cs
- SqlDataSourceEnumerator.cs
- WindowsIdentity.cs
- RangeContentEnumerator.cs
- LinearKeyFrames.cs
- GeometryModel3D.cs
- FirstMatchCodeGroup.cs
- Msmq4PoisonHandler.cs
- HashCodeCombiner.cs
- NullableDoubleSumAggregationOperator.cs
- CodeChecksumPragma.cs
- PathSegment.cs
- ECDiffieHellmanCngPublicKey.cs
- OdbcCommand.cs
- HashRepartitionStream.cs
- XsdDuration.cs
- OutputChannel.cs
- VisualCollection.cs
- StandardToolWindows.cs
- OracleParameter.cs
- InfoCardArgumentException.cs
- DbProviderSpecificTypePropertyAttribute.cs
- CommandID.cs
- TrackBarRenderer.cs
- CombinedGeometry.cs
- ThousandthOfEmRealPoints.cs
- parserscommon.cs
- SimpleWorkerRequest.cs
- DataRelationPropertyDescriptor.cs