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
- ThicknessAnimationBase.cs
- MimeFormatter.cs
- TextSchema.cs
- _OverlappedAsyncResult.cs
- FormsIdentity.cs
- ListViewInsertionMark.cs
- DesignerHost.cs
- ColorIndependentAnimationStorage.cs
- WebPartConnectionsEventArgs.cs
- PnrpPeerResolverBindingElement.cs
- Single.cs
- RelationshipNavigation.cs
- Animatable.cs
- Statements.cs
- EventSinkActivity.cs
- DynamicDataManager.cs
- Wizard.cs
- COM2Properties.cs
- ViewStateModeByIdAttribute.cs
- SourceFileBuildProvider.cs
- SdlChannelSink.cs
- RuntimeConfigLKG.cs
- PrivilegeNotHeldException.cs
- LZCodec.cs
- GroupBox.cs
- EditorZoneBase.cs
- IsolatedStorageFile.cs
- PassportAuthenticationModule.cs
- WindowsFormsHelpers.cs
- UnsafeNativeMethodsMilCoreApi.cs
- EncoderNLS.cs
- SQLSingle.cs
- ErrorWrapper.cs
- ContextProperty.cs
- ResourceLoader.cs
- CodeTryCatchFinallyStatement.cs
- UnsafeNativeMethods.cs
- XmlSerializationGeneratedCode.cs
- ConnectionManagementElement.cs
- DeflateEmulationStream.cs
- PublisherMembershipCondition.cs
- InputReferenceExpression.cs
- ContentValidator.cs
- StructuredProperty.cs
- TerminatorSinks.cs
- MediaContext.cs
- IPAddress.cs
- OrthographicCamera.cs
- xdrvalidator.cs
- DbException.cs
- WasEndpointConfigContainer.cs
- TextServicesCompartmentContext.cs
- XamlParser.cs
- documentation.cs
- ToolStripGrip.cs
- SecurityDescriptor.cs
- LinkArea.cs
- UnregisterInfo.cs
- InternalMappingException.cs
- SoapBinding.cs
- EnumMember.cs
- HttpRequestCacheValidator.cs
- _UncName.cs
- XmlBindingWorker.cs
- OutputCacheProfile.cs
- ActionFrame.cs
- DataAdapter.cs
- ResourceDisplayNameAttribute.cs
- ValidationResult.cs
- TextDecoration.cs
- HorizontalAlignConverter.cs
- ItemCheckedEvent.cs
- TextEditorSpelling.cs
- SafeMemoryMappedViewHandle.cs
- TextChangedEventArgs.cs
- BindingCompleteEventArgs.cs
- QilList.cs
- ConfigurationStrings.cs
- _TransmitFileOverlappedAsyncResult.cs
- WindowsRichEditRange.cs
- IdentityHolder.cs
- SpotLight.cs
- CommunicationObjectManager.cs
- XdrBuilder.cs
- BaseParser.cs
- PrinterUnitConvert.cs
- NullReferenceException.cs
- AssemblyName.cs
- DiffuseMaterial.cs
- Byte.cs
- TripleDES.cs
- TickBar.cs
- TabletDevice.cs
- PageHandlerFactory.cs
- InitialServerConnectionReader.cs
- RowTypePropertyElement.cs
- Exception.cs
- ValidationService.cs
- HttpHandlerActionCollection.cs
- StringValidatorAttribute.cs