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
- EventEntry.cs
- VariableAction.cs
- WindowsListViewItemCheckBox.cs
- ProfileModule.cs
- DynamicRouteExpression.cs
- BufferModeSettings.cs
- Number.cs
- PathFigure.cs
- WindowsNonControl.cs
- ClipboardData.cs
- SqlMultiplexer.cs
- KeyboardDevice.cs
- TemplateControl.cs
- MenuItemBindingCollection.cs
- InterleavedZipPartStream.cs
- Component.cs
- ConfigXmlAttribute.cs
- NetSectionGroup.cs
- CounterSampleCalculator.cs
- PeerNameRegistration.cs
- XmlAnyElementAttribute.cs
- OdbcParameterCollection.cs
- SQLDecimalStorage.cs
- StateManagedCollection.cs
- TextElementEnumerator.cs
- ClientEventManager.cs
- Color.cs
- OletxTransactionFormatter.cs
- UnknownBitmapDecoder.cs
- TextSpanModifier.cs
- SystemInfo.cs
- PackWebRequestFactory.cs
- DataListCommandEventArgs.cs
- WebPartEditorApplyVerb.cs
- ToolStripRendererSwitcher.cs
- PersistenceProviderFactory.cs
- HttpCacheParams.cs
- DropShadowEffect.cs
- UrlMapping.cs
- Attribute.cs
- JavaScriptObjectDeserializer.cs
- Duration.cs
- KeysConverter.cs
- ResourceLoader.cs
- M3DUtil.cs
- HtmlValidatorAdapter.cs
- EventQueueState.cs
- OpCellTreeNode.cs
- ListViewUpdatedEventArgs.cs
- XmlSerializerImportOptions.cs
- CqlParser.cs
- LockedBorderGlyph.cs
- SQLMoney.cs
- ScrollBarRenderer.cs
- ApplicationActivator.cs
- RtfControls.cs
- NameHandler.cs
- AttributeInfo.cs
- OletxDependentTransaction.cs
- UInt32Storage.cs
- Unit.cs
- DropShadowBitmapEffect.cs
- DragStartedEventArgs.cs
- FixedElement.cs
- PatternMatchRules.cs
- RelationshipDetailsRow.cs
- categoryentry.cs
- ProfilePropertyNameValidator.cs
- LinqDataSourceValidationException.cs
- ConfigXmlComment.cs
- FormClosingEvent.cs
- HandledMouseEvent.cs
- ConvertersCollection.cs
- Comparer.cs
- SrgsItemList.cs
- AnnotationResourceCollection.cs
- StateManagedCollection.cs
- EditorZoneBase.cs
- DesignerCategoryAttribute.cs
- CellTreeNodeVisitors.cs
- EntityContainer.cs
- PenLineCapValidation.cs
- ApplicationServiceManager.cs
- Pair.cs
- HttpResponseHeader.cs
- OdbcConnectionFactory.cs
- ObjectFullSpanRewriter.cs
- NotifyCollectionChangedEventArgs.cs
- DynamicValidator.cs
- ExpandedWrapper.cs
- FtpWebRequest.cs
- PathBox.cs
- SelectionGlyph.cs
- UnknownWrapper.cs
- StandardTransformFactory.cs
- AsyncDataRequest.cs
- KeyboardDevice.cs
- InvalidComObjectException.cs
- DataDocumentXPathNavigator.cs
- CounterSetInstanceCounterDataSet.cs