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
- PointKeyFrameCollection.cs
- CompilerGlobalScopeAttribute.cs
- DispatcherHookEventArgs.cs
- CollectionBuilder.cs
- TraceListeners.cs
- documentation.cs
- NonBatchDirectoryCompiler.cs
- XmlComment.cs
- Light.cs
- HttpListenerContext.cs
- ParameterBuilder.cs
- CommandEventArgs.cs
- VerificationAttribute.cs
- InternalUserCancelledException.cs
- TemplatedWizardStep.cs
- HelpEvent.cs
- XmlSchemaAll.cs
- DesignerCategoryAttribute.cs
- ExpressionBuilder.cs
- PhotoPrintingIntent.cs
- SmtpFailedRecipientsException.cs
- AuthorizationSection.cs
- StringArrayConverter.cs
- AssemblyHelper.cs
- SapiRecoInterop.cs
- TextParagraphProperties.cs
- EdmComplexTypeAttribute.cs
- DataViewSetting.cs
- BuildResult.cs
- EdmItemError.cs
- CompiledIdentityConstraint.cs
- CompositeFontParser.cs
- LinkClickEvent.cs
- UrlMappingsModule.cs
- XmlCDATASection.cs
- BaseCAMarshaler.cs
- MediaContext.cs
- MostlySingletonList.cs
- OleDbErrorCollection.cs
- SByteStorage.cs
- _DigestClient.cs
- TypeListConverter.cs
- AdRotator.cs
- UserControlBuildProvider.cs
- XmlSchemaAnnotated.cs
- TcpTransportManager.cs
- HyperLinkStyle.cs
- XmlAttributes.cs
- ItemsPanelTemplate.cs
- SynchronizationContext.cs
- fixedPageContentExtractor.cs
- ScriptingWebServicesSectionGroup.cs
- HtmlControl.cs
- NameHandler.cs
- CacheMode.cs
- DockPanel.cs
- PeerNameRecordCollection.cs
- TextChangedEventArgs.cs
- CompModSwitches.cs
- _ContextAwareResult.cs
- WebPartMenuStyle.cs
- QilFunction.cs
- SoapServerMessage.cs
- StatusBarDrawItemEvent.cs
- ActivitySurrogateSelector.cs
- pingexception.cs
- DataServiceQueryOfT.cs
- OdbcException.cs
- EntityKeyElement.cs
- StandardOleMarshalObject.cs
- BaseComponentEditor.cs
- ISAPIApplicationHost.cs
- FixedSOMTableRow.cs
- FontSource.cs
- externdll.cs
- ShimAsPublicXamlType.cs
- ExtendedPropertyDescriptor.cs
- ExpressionLexer.cs
- SpnegoTokenProvider.cs
- LineBreakRecord.cs
- ClientUrlResolverWrapper.cs
- cache.cs
- SafeRightsManagementEnvironmentHandle.cs
- TableCellAutomationPeer.cs
- ModelFunction.cs
- DbMetaDataFactory.cs
- PenContext.cs
- ParserStreamGeometryContext.cs
- CustomValidator.cs
- XmlByteStreamWriter.cs
- MediaContext.cs
- TimeEnumHelper.cs
- GifBitmapEncoder.cs
- IntranetCredentialPolicy.cs
- MergeFailedEvent.cs
- Window.cs
- DataRowChangeEvent.cs
- XmlAggregates.cs
- ParseElementCollection.cs
- ISFClipboardData.cs