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
- KeyValueConfigurationCollection.cs
- MostlySingletonList.cs
- FunctionUpdateCommand.cs
- ConnectorDragDropGlyph.cs
- DataGridViewImageCell.cs
- TemplateBindingExpression.cs
- MTConfigUtil.cs
- DeflateStream.cs
- GeneratedCodeAttribute.cs
- EntityDataSourceChangedEventArgs.cs
- PolicyManager.cs
- SqlConnectionString.cs
- ResXBuildProvider.cs
- SqlEnums.cs
- TextEncodedRawTextWriter.cs
- TypeProvider.cs
- Message.cs
- SqlDeflator.cs
- dataprotectionpermission.cs
- TabItemAutomationPeer.cs
- XmlSerializer.cs
- Site.cs
- sqlmetadatafactory.cs
- PartitionResolver.cs
- FileVersionInfo.cs
- ErrorTableItemStyle.cs
- CultureTableRecord.cs
- BookmarkScopeManager.cs
- SQLBinary.cs
- Fx.cs
- DataGrid.cs
- ProtocolsSection.cs
- AdapterUtil.cs
- WebPartMenuStyle.cs
- IIS7WorkerRequest.cs
- Odbc32.cs
- ClaimTypes.cs
- DataSourceComponent.cs
- HtmlTernaryTree.cs
- OperationAbortedException.cs
- VariableQuery.cs
- TypeConstant.cs
- QuerySafeNavigator.cs
- PTProvider.cs
- HttpResponseMessageProperty.cs
- LabelDesigner.cs
- IndependentlyAnimatedPropertyMetadata.cs
- ComponentRenameEvent.cs
- ColumnResult.cs
- DataControlExtensions.cs
- TheQuery.cs
- FixedTextSelectionProcessor.cs
- NativeBuffer.cs
- Grant.cs
- safelinkcollection.cs
- PassportAuthenticationModule.cs
- JsonQNameDataContract.cs
- InternalDispatchObject.cs
- ExpressionWriter.cs
- ScriptReference.cs
- LowerCaseStringConverter.cs
- DefaultParameterValueAttribute.cs
- odbcmetadatacolumnnames.cs
- TokenBasedSetEnumerator.cs
- TaskFileService.cs
- SessionPageStatePersister.cs
- XmlSchemaComplexContent.cs
- HostingEnvironmentSection.cs
- InternalTransaction.cs
- ServiceModelConfigurationElementCollection.cs
- EventHandlers.cs
- BitConverter.cs
- ApplicationHost.cs
- PolyLineSegment.cs
- Brush.cs
- EnglishPluralizationService.cs
- PreDigestedSignedInfo.cs
- InputReferenceExpression.cs
- SelectionRange.cs
- ButtonFlatAdapter.cs
- QilReference.cs
- StaticResourceExtension.cs
- AnnotationAdorner.cs
- SymbolType.cs
- EditingCoordinator.cs
- XmlSchemas.cs
- XmlEncoding.cs
- BuildResult.cs
- DataChangedEventManager.cs
- LogicalExpr.cs
- Section.cs
- PageParser.cs
- CanExecuteRoutedEventArgs.cs
- DocumentApplication.cs
- SQLSingleStorage.cs
- RemoveStoryboard.cs
- PropertyEmitterBase.cs
- PointAnimationBase.cs
- DataBoundLiteralControl.cs
- MD5CryptoServiceProvider.cs