Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / Dispatcher / CorrelationKeyCalculator.cs / 1305376 / CorrelationKeyCalculator.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.ServiceModel.Activities.Dispatcher { using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.Runtime.Collections; using System.Runtime.Diagnostics; using System.Runtime.DurableInstancing; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Diagnostics; using System.ServiceModel.Dispatcher; using System.Xml.Linq; using System.Text; using SR2 = System.ServiceModel.Activities.SR; class CorrelationKeyCalculator { MessageBufferCalculator bufferCalculator; MessageCalculator messageCalculator; XName scopeName; MessageFilterTablewhereRuntime; CorrelationKeyCache keyCache; public CorrelationKeyCalculator(XName scopeName) { this.whereRuntime = new MessageFilterTable (); this.scopeName = scopeName; this.keyCache = new CorrelationKeyCache(); } public void AddQuery(MessageFilter where, MessageQueryTable select, IDictionary > selectAdditional, bool isContextQuery) { SelectRuntime selectRuntime = new SelectRuntime { Select = select, SelectAdditional = selectAdditional, IsContextQuery = isContextQuery }; this.whereRuntime.Add(where, selectRuntime); } public bool CalculateKeys(Message message, out InstanceKey instanceKey, out ICollection additionalKeys) { MessageCalculator calculator = this.messageCalculator; if (calculator == null) { calculator = this.messageCalculator = new MessageCalculator(this); } return calculator.CalculateKeys(message, null, out instanceKey, out additionalKeys); } public bool CalculateKeys(MessageBuffer buffer, Message messageToReadHeaders, out InstanceKey instanceKey, out ICollection additionalKeys) { MessageBufferCalculator calculator = this.bufferCalculator; if (calculator == null) { calculator = this.bufferCalculator = new MessageBufferCalculator(this); } return calculator.CalculateKeys(buffer, messageToReadHeaders, out instanceKey, out additionalKeys); } abstract class Calculator { CorrelationKeyCalculator parent; public Calculator(CorrelationKeyCalculator parent) { this.parent = parent; } public bool CalculateKeys(T target, Message messageToReadHeaders, out InstanceKey instanceKey, out ICollection additionalKeys) { SelectRuntime select; instanceKey = InstanceKey.InvalidKey; additionalKeys = null; // this is a query on the serverside, either Receive or SendReply // Where if (!this.ExecuteWhere(target, messageToReadHeaders, this.parent.whereRuntime, out select)) { return false; } Dictionary values = new Dictionary (); // Select if (select.Select.Count > 0) { bool allOptional = true; foreach (KeyValuePair result in this.ExecuteSelect(target, messageToReadHeaders, select.Select, select.IsContextQuery)) { if (!(result.Key is OptionalMessageQuery)) { allOptional = false; } if (!string.IsNullOrEmpty(result.Value)) { values.Add(select.Select[result.Key], result.Value); } } if (values.Count == 0) { if (!allOptional) { throw FxTrace.Exception.AsError(new ProtocolException(SR2.EmptyCorrelationQueryResults)); } } else { instanceKey = this.GetInstanceKey(values); if (TD.TraceCorrelationKeysIsEnabled()) { TraceCorrelationKeys(instanceKey, values); } } } // SelectAdditional foreach (KeyValuePair > item in select.SelectAdditional) { if (additionalKeys == null) { additionalKeys = new List (); } values.Clear(); InstanceKey additionalKey = InstanceKey.InvalidKey; bool allOptional = true; foreach (KeyValuePair result in this.ExecuteSelect(target, messageToReadHeaders, item.Value, select.IsContextQuery)) { if (!(result.Key is OptionalMessageQuery)) { allOptional = false; } if (!string.IsNullOrEmpty(result.Value)) { values.Add(item.Value[result.Key], result.Value); } } if (values.Count == 0) { if (!allOptional) { throw FxTrace.Exception.AsError(new ProtocolException(SR2.EmptyCorrelationQueryResults)); } } else { additionalKey = new CorrelationKey(values, this.parent.scopeName.ToString(), null) { Name = item.Key }; if (TD.TraceCorrelationKeysIsEnabled()) { TraceCorrelationKeys(additionalKey, values); } } additionalKeys.Add(additionalKey); } return true; } CorrelationKey GetInstanceKey(Dictionary values) { // We only optimize for upto 3 keys if (values.Count <= 3) { CorrelationKey correlationKey; CorrelationCacheKey cacheKey = CorrelationCacheKey.CreateKey(values); if (this.parent.keyCache.TryGetValue(cacheKey, out correlationKey)) { return correlationKey; } correlationKey = new CorrelationKey(values, this.parent.scopeName.ToString(), null); this.parent.keyCache.Add(cacheKey, correlationKey); return correlationKey; } return new CorrelationKey(values, this.parent.scopeName.ToString(), null); } protected abstract IEnumerable > ExecuteSelect(T target, Message messageToReadHeaders, MessageQueryTable select, bool IsContextQuery); protected abstract bool ExecuteWhere(T target, Message messageToReadHeaders, MessageFilterTable whereRuntime, out SelectRuntime select); void TraceCorrelationKeys(InstanceKey instanceKey, Dictionary values) { StringBuilder keyValueAsString = new StringBuilder(); foreach (KeyValuePair pair in values) { keyValueAsString.Append(pair.Key).Append(":").Append(pair.Value).Append(','); } TD.TraceCorrelationKeys(instanceKey.Value, keyValueAsString.ToString(), this.parent.scopeName.ToString()); } } class MessageBufferCalculator : Calculator { public MessageBufferCalculator(CorrelationKeyCalculator parent) : base(parent) { } protected override IEnumerable > ExecuteSelect(MessageBuffer target, Message messageToReadHeaders, MessageQueryTable select, bool isContextQuery) { if (isContextQuery && messageToReadHeaders != null) { //we can pass in the message directly in this case since we know it is a context query that will read from the header return select.Evaluate (messageToReadHeaders); } else { return select.Evaluate (target); } } protected override bool ExecuteWhere(MessageBuffer target, Message messageToReadHeaders, MessageFilterTable whereRuntime, out SelectRuntime select) { return whereRuntime.GetMatchingValue(target, messageToReadHeaders, out select); } } [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "Will use this once correlation with streaming is fixed")] class MessageCalculator : Calculator { [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "Will use this once correlation with streaming is fixed")] public MessageCalculator(CorrelationKeyCalculator parent) : base(parent) { } protected override IEnumerable > ExecuteSelect(Message target, Message messageToReadHeaders, MessageQueryTable select, bool isContextQuery) { return select.Evaluate (target); } protected override bool ExecuteWhere(Message target, Message messageToReadHeaders, MessageFilterTable whereRuntime, out SelectRuntime select) { // messageToReadHeaders is not used in case of MessageCalculator return whereRuntime.GetMatchingValue(target, out select); } } class SelectRuntime { public MessageQueryTable Select { get; set; } public IDictionary > SelectAdditional { get; set; } internal bool IsContextQuery { get; set; } } // Needs to seperate from the generic calculator as all jitted types // should share the same cache. class CorrelationKeyCache { HopperCache cache; object cacheLock; internal CorrelationKeyCache() { this.cache = new HopperCache(128, false); this.cacheLock = new object(); } internal void Add(CorrelationCacheKey key, CorrelationKey value) { Fx.Assert(key != null, "Cannot add a null CorrelationCacheKey to the cache."); lock (this.cacheLock) { this.cache.Add(key, value); } } internal bool TryGetValue(CorrelationCacheKey key, out CorrelationKey value) { value = (CorrelationKey)this.cache.GetValue(this.cacheLock, key); return (value != null); } } abstract class CorrelationCacheKey { static internal CorrelationCacheKey CreateKey(Dictionary keys) { if (keys.Count == 1) { return new SingleCacheKey(keys); } else { return new MultipleCacheKey(keys); } } static int CombineHashCodes(int h1, int h2) { return (((h1 << 5) + h1) ^ h2); } class SingleCacheKey : CorrelationCacheKey { int hashCode; string key; string value; public SingleCacheKey(Dictionary keys) { Fx.Assert(keys.Count == 1, "Cannot intialize CorrelationCacheSingleKey with multiple key values."); foreach (KeyValuePair keyValue in keys) { this.key = keyValue.Key; this.value = keyValue.Value; this.hashCode = CombineHashCodes(this.key.GetHashCode(), this.value.GetHashCode()); return; } } public override bool Equals(object obj) { SingleCacheKey target = obj as SingleCacheKey; return (target != null && (this.hashCode == target.hashCode) && ((this.key == target.key) && (this.value == target.value))); } public override int GetHashCode() { return this.hashCode; } } class MultipleCacheKey : CorrelationCacheKey { Dictionary keyValues; int hashCode; public MultipleCacheKey(Dictionary keys) { this.keyValues = keys; foreach (KeyValuePair keyValue in this.keyValues) { int hash1 = CombineHashCodes(this.hashCode, keyValue.Key.GetHashCode()); this.hashCode = CombineHashCodes(hash1, keyValue.Value.GetHashCode()); } } public override bool Equals(object obj) { MultipleCacheKey target = obj as MultipleCacheKey; if (target != null) { if ((this.hashCode == target.hashCode) && (this.keyValues.Count == target.keyValues.Count)) { string sourceValue; foreach (KeyValuePair targetKeyValue in target.keyValues) { if (!this.keyValues.TryGetValue(targetKeyValue.Key, out sourceValue) || sourceValue != targetKeyValue.Value) { return false; } } //All keys and values are the same return true; } } return false; } public override int GetHashCode() { return this.hashCode; } } } } } // 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
- AddressHeader.cs
- LocatorBase.cs
- BmpBitmapDecoder.cs
- WindowsImpersonationContext.cs
- AmbiguousMatchException.cs
- MaterialCollection.cs
- ConnectionManagementElementCollection.cs
- TextViewBase.cs
- XmlAtomicValue.cs
- TransformerInfoCollection.cs
- EdmProviderManifest.cs
- CodeAttachEventStatement.cs
- StandardToolWindows.cs
- BamlWriter.cs
- BinaryObjectReader.cs
- ToolStripArrowRenderEventArgs.cs
- TransformGroup.cs
- CookielessData.cs
- ExpressionBuilderCollection.cs
- ApplicationBuildProvider.cs
- Propagator.Evaluator.cs
- Switch.cs
- SettingsSection.cs
- ParameterBinding.cs
- DbMetaDataFactory.cs
- SamlConditions.cs
- FontSourceCollection.cs
- ControlValuePropertyAttribute.cs
- CngProperty.cs
- CodeDOMProvider.cs
- BooleanToVisibilityConverter.cs
- SafeFileMapViewHandle.cs
- TypeInfo.cs
- DataGridViewSelectedRowCollection.cs
- ThreadStateException.cs
- RsaKeyIdentifierClause.cs
- SlipBehavior.cs
- PartialCachingControl.cs
- StringStorage.cs
- Propagator.cs
- ExtendedProtectionPolicy.cs
- COAUTHINFO.cs
- ConsumerConnectionPointCollection.cs
- CellLabel.cs
- RawKeyboardInputReport.cs
- DebugTraceHelper.cs
- DataContract.cs
- StaticExtension.cs
- _SslSessionsCache.cs
- ArrayTypeMismatchException.cs
- X509AsymmetricSecurityKey.cs
- PseudoWebRequest.cs
- MouseButtonEventArgs.cs
- DocumentViewerBaseAutomationPeer.cs
- TextEndOfParagraph.cs
- MeasureItemEvent.cs
- HostProtectionPermission.cs
- ListViewGroupItemCollection.cs
- PersonalizationState.cs
- InputBinding.cs
- BitStream.cs
- EFDataModelProvider.cs
- panel.cs
- ActionFrame.cs
- StorageBasedPackageProperties.cs
- OleServicesContext.cs
- BooleanToSelectiveScrollingOrientationConverter.cs
- InvalidateEvent.cs
- EdmEntityTypeAttribute.cs
- AudioFileOut.cs
- MultipartContentParser.cs
- DrawingAttributesDefaultValueFactory.cs
- ConfigurationElementCollection.cs
- HttpModulesSection.cs
- XmlSchemaSimpleTypeList.cs
- UpWmlPageAdapter.cs
- PhonemeEventArgs.cs
- HostingEnvironment.cs
- UnionCodeGroup.cs
- Attribute.cs
- PersonalizationProviderCollection.cs
- DrawListViewSubItemEventArgs.cs
- XsdDuration.cs
- TransportSecurityProtocol.cs
- RemotingHelper.cs
- X509InitiatorCertificateServiceElement.cs
- RotationValidation.cs
- SortableBindingList.cs
- SafeRightsManagementPubHandle.cs
- WebResponse.cs
- ProxyManager.cs
- FontFamilyIdentifier.cs
- ParseChildrenAsPropertiesAttribute.cs
- StringCollectionMarkupSerializer.cs
- XmlSchemaDatatype.cs
- SelectedDatesCollection.cs
- IpcChannel.cs
- TdsParserSessionPool.cs
- ToolZone.cs
- BitmapEffectCollection.cs