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
- AssemblyCache.cs
- ThreadStateException.cs
- precedingsibling.cs
- hresults.cs
- SchemaNamespaceManager.cs
- CompressEmulationStream.cs
- WindowsListViewScroll.cs
- DBSqlParserColumn.cs
- UserNameSecurityToken.cs
- MulticastIPAddressInformationCollection.cs
- GridSplitterAutomationPeer.cs
- StorageEndPropertyMapping.cs
- SqlAggregateChecker.cs
- XmlSchemaException.cs
- ButtonAutomationPeer.cs
- CollectionViewSource.cs
- ConfigXmlElement.cs
- DataExpression.cs
- PassportPrincipal.cs
- Group.cs
- ExtenderControl.cs
- XmlFormatExtensionAttribute.cs
- HttpFileCollection.cs
- ImportContext.cs
- ModelPropertyCollectionImpl.cs
- OdbcError.cs
- EditorAttribute.cs
- MSG.cs
- WaitHandle.cs
- ToolboxBitmapAttribute.cs
- SimpleRecyclingCache.cs
- PagesChangedEventArgs.cs
- RequiredFieldValidator.cs
- SqlMetaData.cs
- EventMappingSettings.cs
- ChunkedMemoryStream.cs
- FactoryId.cs
- UndoManager.cs
- ItemCollection.cs
- ObjectSelectorEditor.cs
- HMACMD5.cs
- OrCondition.cs
- JoinCqlBlock.cs
- MemberPath.cs
- GenericQueueSurrogate.cs
- ItemsControl.cs
- DisableDpiAwarenessAttribute.cs
- CustomSignedXml.cs
- DbDeleteCommandTree.cs
- DataServiceQueryProvider.cs
- MsmqTransportSecurityElement.cs
- _ListenerResponseStream.cs
- RangeEnumerable.cs
- ProcessManager.cs
- ItemTypeToolStripMenuItem.cs
- X509ChainPolicy.cs
- DbBuffer.cs
- figurelength.cs
- EncoderBestFitFallback.cs
- AppManager.cs
- TableCellCollection.cs
- TemplateControlBuildProvider.cs
- UpdatePanelControlTrigger.cs
- SelectedDatesCollection.cs
- RelationalExpressions.cs
- NetMsmqBindingCollectionElement.cs
- LogWriteRestartAreaState.cs
- DriveNotFoundException.cs
- PageAsyncTask.cs
- NotSupportedException.cs
- X509ChainElement.cs
- WmpBitmapDecoder.cs
- ValidationHelper.cs
- EmbeddedMailObjectsCollection.cs
- DirectoryLocalQuery.cs
- InArgument.cs
- MaskedTextBoxDesigner.cs
- TrimSurroundingWhitespaceAttribute.cs
- FragmentNavigationEventArgs.cs
- AttachedPropertyBrowsableForChildrenAttribute.cs
- PrintDialog.cs
- OneOfScalarConst.cs
- WsdlImporterElement.cs
- AppDomain.cs
- TreeNodeBinding.cs
- TreeViewImageKeyConverter.cs
- SqlConnectionFactory.cs
- HandoffBehavior.cs
- SerialReceived.cs
- Win32.cs
- TreeNode.cs
- codemethodreferenceexpression.cs
- SafeArrayRankMismatchException.cs
- ObjectSecurity.cs
- SecurityRequiresReviewAttribute.cs
- AssertSection.cs
- ModelTreeEnumerator.cs
- SmtpReplyReader.cs
- SqlDataSource.cs
- ProtocolsInstallComponent.cs