Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / UriPrefixTable.cs / 1 / UriPrefixTable.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.ServiceModel.Channels { using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Net; using System.ServiceModel.Diagnostics; using System.Text; using System.Threading; using System.Web; using System.Web.Hosting; sealed class UriPrefixTablewhere TItem : class { int count; MruCache lookupCache; // cache matches, for lookup speed // separate table for WeakReference usage MruCache weakLookupCache; SegmentHierarchyNode root; bool useWeakReferences; bool includePortInComparison; public UriPrefixTable() : this(false) { } public UriPrefixTable(bool includePortInComparison) : this(includePortInComparison, false) { } public UriPrefixTable(bool includePortInComparison, bool useWeakReferences) { const int mruWatermark = 128; this.includePortInComparison = includePortInComparison; this.useWeakReferences = useWeakReferences; this.root = new SegmentHierarchyNode (null, useWeakReferences); if (useWeakReferences) { this.weakLookupCache = new MruCache (mruWatermark); } else { this.lookupCache = new MruCache (mruWatermark); } } object ThisLock { get { return this; } } public int Count { get { return this.count; } } public bool IsRegistered(BaseUriWithWildcard key) { Uri uri = key.BaseAddress; // don't need to normalize path since SegmentHierarchyNode is // already OrdinalIgnoreCase string[] paths = UriSegmenter.ToPath(uri, key.HostNameComparisonMode, this.includePortInComparison); bool exactMatch; SegmentHierarchyNode node; lock (ThisLock) { node = FindDataNode(paths, out exactMatch); } return exactMatch && node != null && node.Data != null; } public IEnumerable > GetAll() { lock (ThisLock) { List > result = new List >(); this.root.Collect(result); return result; } } bool TryCacheLookup(BaseUriWithWildcard key, out TItem item) { if (useWeakReferences) { WeakReference itemReference; if (this.weakLookupCache.TryGetValue(key, out itemReference)) { item = itemReference.Target as TItem; if (item != null) { return true; } else // dead link { this.weakLookupCache.Remove(key); } } } else { return this.lookupCache.TryGetValue(key, out item); } item = null; return false; } void AddToCache(BaseUriWithWildcard key, TItem item) { if (useWeakReferences) { this.weakLookupCache.Add(key, new WeakReference(item)); } else { this.lookupCache.Add(key, item); } } void ClearCache() { if (useWeakReferences) { this.weakLookupCache.Clear(); } else { this.lookupCache.Clear(); } } public bool TryLookupUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, out TItem item) { item = null; BaseUriWithWildcard key = new BaseUriWithWildcard(uri, hostNameComparisonMode); lock (ThisLock) { bool isCached = TryCacheLookup(key, out item); if (!isCached) { // exact match failed, perform the full lookup (which will also // catch case-insensitive variations that aren't yet in our cache) bool dummy; SegmentHierarchyNode node = FindDataNode( UriSegmenter.ToPath(key.BaseAddress, hostNameComparisonMode, this.includePortInComparison), out dummy); if (node != null) { item = node.Data; } // We want to cache both positive AND negative results AddToCache(key, item); } return (item != null); } } public void RegisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, TItem item) { DiagnosticUtility.DebugAssert(HostNameComparisonModeHelper.IsDefined(hostNameComparisonMode), "RegisterUri: Invalid HostNameComparisonMode value passed in."); lock (ThisLock) { // Since every newly registered Uri could alter what Prefixes should have matched, we // should clear the cache of any existing results and start over ClearCache(); BaseUriWithWildcard key = new BaseUriWithWildcard(uri, hostNameComparisonMode); SegmentHierarchyNode node = FindOrCreateNode(key); if (node.Data != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString( SR.DuplicateRegistration, uri))); } node.SetData(item, key); count++; } } public void UnregisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode) { lock (ThisLock) { // Since every removed Uri could alter what Prefixes should have matched, we // should clear the cache of any existing results and start over ClearCache(); string[] path = UriSegmenter.ToPath(uri, hostNameComparisonMode, this.includePortInComparison); // Never remove the root if (path.Length == 0) { this.root.RemoveData(); } else { this.root.RemovePath(path, 0); } count--; } } SegmentHierarchyNode FindDataNode(string[] path, out bool exactMatch) { DiagnosticUtility.DebugAssert(path != null, "FindDataNode: path is null"); exactMatch = false; SegmentHierarchyNode current = this.root; SegmentHierarchyNode result = null; for (int i = 0; i < path.Length; ++i) { SegmentHierarchyNode next; if (!current.TryGetChild(path[i], out next)) { break; } else if (next.Data != null) { result = next; exactMatch = (i == path.Length - 1); } current = next; } return result; } SegmentHierarchyNode FindOrCreateNode(BaseUriWithWildcard baseUri) { DiagnosticUtility.DebugAssert(baseUri != null, "FindOrCreateNode: baseUri is null"); string[] path = UriSegmenter.ToPath(baseUri.BaseAddress, baseUri.HostNameComparisonMode, this.includePortInComparison); SegmentHierarchyNode current = this.root; for (int i = 0; i < path.Length; ++i) { SegmentHierarchyNode next; if (!current.TryGetChild(path[i], out next)) { next = new SegmentHierarchyNode (path[i], useWeakReferences); current.SetChildNode(path[i], next); } current = next; } return current; } static class UriSegmenter { internal static string[] ToPath(Uri uriPath, HostNameComparisonMode hostNameComparisonMode, bool includePortInComparison) { if (null == uriPath) { return new string[0]; } UriSegmentEnum segmentEnum = new UriSegmentEnum(uriPath); // struct return segmentEnum.GetSegments(hostNameComparisonMode, includePortInComparison); } struct UriSegmentEnum { string segment; int segmentStartAt; int segmentLength; UriSegmentType type; Uri uri; internal UriSegmentEnum(Uri uri) { DiagnosticUtility.DebugAssert(null != uri, "UreSegmentEnum: null uri"); this.uri = uri; this.type = UriSegmentType.Unknown; this.segment = null; this.segmentStartAt = 0; this.segmentLength = 0; } void ClearSegment() { this.type = UriSegmentType.None; this.segment = string.Empty; this.segmentStartAt = 0; this.segmentLength = 0; } public string[] GetSegments(HostNameComparisonMode hostNameComparisonMode, bool includePortInComparison) { List segments = new List (); while (this.Next()) { switch (this.type) { case UriSegmentType.Path: segments.Add(this.segment.Substring(this.segmentStartAt, this.segmentLength)); break; case UriSegmentType.Host: if (hostNameComparisonMode == HostNameComparisonMode.StrongWildcard) { segments.Add("+"); } else if (hostNameComparisonMode == HostNameComparisonMode.Exact) { segments.Add(this.segment); } else { segments.Add("*"); } break; case UriSegmentType.Port: if (includePortInComparison || hostNameComparisonMode == HostNameComparisonMode.Exact) { segments.Add(this.segment); } break; default: segments.Add(this.segment); break; } } return segments.ToArray(); } public bool Next() { while (true) { switch (this.type) { case UriSegmentType.Unknown: this.type = UriSegmentType.Scheme; this.SetSegment(this.uri.Scheme); return true; case UriSegmentType.Scheme: this.type = UriSegmentType.Host; string host = this.uri.Host; // The userName+password also accompany... string userInfo = this.uri.UserInfo; if (null != userInfo && userInfo.Length > 0) { host = userInfo + '@' + host; } this.SetSegment(host); return true; case UriSegmentType.Host: this.type = UriSegmentType.Port; int port = this.uri.Port; this.SetSegment(port.ToString(CultureInfo.InvariantCulture)); return true; case UriSegmentType.Port: this.type = UriSegmentType.Path; string absPath = this.uri.AbsolutePath; DiagnosticUtility.DebugAssert(null != absPath, "Next: nill absPath"); if (0 == absPath.Length) { this.ClearSegment(); return false; } this.segment = absPath; this.segmentStartAt = 0; this.segmentLength = 0; return this.NextPathSegment(); case UriSegmentType.Path: return this.NextPathSegment(); case UriSegmentType.None: return false; default: DiagnosticUtility.DebugAssert("Next: unknown enum value"); return false; } } } public bool NextPathSegment() { this.segmentStartAt += this.segmentLength; while (this.segmentStartAt < this.segment.Length && this.segment[this.segmentStartAt] == '/') { this.segmentStartAt++; } if (this.segmentStartAt < this.segment.Length) { int next = this.segment.IndexOf('/', this.segmentStartAt); if (-1 == next) { this.segmentLength = this.segment.Length - this.segmentStartAt; } else { this.segmentLength = next - this.segmentStartAt; } return true; } this.ClearSegment(); return false; } void SetSegment(string segment) { this.segment = segment; this.segmentStartAt = 0; this.segmentLength = segment.Length; } enum UriSegmentType { Unknown, Scheme, Host, Port, Path, None } } } } class SegmentHierarchyNode where TData : class { BaseUriWithWildcard path; TData data; string name; Dictionary > children; WeakReference weakData; bool useWeakReferences; public SegmentHierarchyNode(string name, bool useWeakReferences) { this.name = name; this.useWeakReferences = useWeakReferences; this.children = new Dictionary >(StringComparer.OrdinalIgnoreCase); } public TData Data { get { if (useWeakReferences) { if (this.weakData == null) { return null; } else { return this.weakData.Target as TData; } } else { return this.data; } } } public void SetData(TData data, BaseUriWithWildcard path) { this.path = path; if (useWeakReferences) { if (data == null) { this.weakData = null; } else { this.weakData = new WeakReference(data); } } else { this.data = data; } } public void SetChildNode(string name, SegmentHierarchyNode node) { this.children[name] = node; } public void Collect(List > result) { TData localData = this.Data; if (localData != null) { result.Add(new KeyValuePair (path, localData)); } foreach (SegmentHierarchyNode child in this.children.Values) { child.Collect(result); } } public bool TryGetChild(string segment, out SegmentHierarchyNode value) { return children.TryGetValue(segment, out value); } public void RemoveData() { SetData(null, null); } // bool is whether to remove this node public bool RemovePath(string[] path, int seg) { if (seg == path.Length) { RemoveData(); return this.children.Count == 0; } SegmentHierarchyNode node; if (!TryGetChild(path[seg], out node)) { return (this.children.Count == 0 && Data == null); } if (node.RemovePath(path, seg + 1)) { this.children.Remove(path[seg]); return (this.children.Count == 0 && Data == null); } else { return false; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DesignSurfaceServiceContainer.cs
- TypeInfo.cs
- Timer.cs
- WebPartDisplayModeCancelEventArgs.cs
- Compilation.cs
- ConsoleKeyInfo.cs
- ThicknessAnimationUsingKeyFrames.cs
- MemberAssignmentAnalysis.cs
- LazyTextWriterCreator.cs
- CompressStream.cs
- XmlFormatMapping.cs
- IOException.cs
- RoleManagerModule.cs
- HtmlProps.cs
- HtmlGenericControl.cs
- Line.cs
- JoinSymbol.cs
- AttributeEmitter.cs
- CompareValidator.cs
- ListViewItem.cs
- GroupBoxRenderer.cs
- DesignTableCollection.cs
- XamlWrappingReader.cs
- QueryCacheKey.cs
- CodeStatementCollection.cs
- TypedTableBase.cs
- brushes.cs
- UIElementHelper.cs
- IdnElement.cs
- BufferedGraphicsManager.cs
- ListChangedEventArgs.cs
- ChannelBinding.cs
- SqlTriggerContext.cs
- DataGridAddNewRow.cs
- HighlightVisual.cs
- BaseTemplateParser.cs
- HtmlLabelAdapter.cs
- DataGridViewColumnDividerDoubleClickEventArgs.cs
- StorageEntitySetMapping.cs
- PathFigure.cs
- BaseResourcesBuildProvider.cs
- XomlSerializationHelpers.cs
- BinaryMethodMessage.cs
- SchemaTableOptionalColumn.cs
- ListItemConverter.cs
- GlobalProxySelection.cs
- GlobalizationAssembly.cs
- AbsoluteQuery.cs
- UMPAttributes.cs
- OdbcDataAdapter.cs
- DoubleLinkList.cs
- ClientFormsIdentity.cs
- CodeDirectiveCollection.cs
- RunClient.cs
- InOutArgumentConverter.cs
- DataGridAutomationPeer.cs
- brushes.cs
- FillErrorEventArgs.cs
- ValidationRule.cs
- Timer.cs
- DataGridLinkButton.cs
- BindingCompleteEventArgs.cs
- SHA384.cs
- TabItemAutomationPeer.cs
- ManifestResourceInfo.cs
- PolyQuadraticBezierSegmentFigureLogic.cs
- OrderingExpression.cs
- DomNameTable.cs
- PickBranchDesigner.xaml.cs
- ServiceDescription.cs
- RemotingServices.cs
- ToolStripDropDownClosingEventArgs.cs
- NativeMethods.cs
- DataGridViewCellParsingEventArgs.cs
- AssemblyBuilderData.cs
- InlineCollection.cs
- DoubleAnimationUsingPath.cs
- PLINQETWProvider.cs
- DataBindingExpressionBuilder.cs
- VisualBrush.cs
- ProcessManager.cs
- PropertyIdentifier.cs
- OutputCacheProfile.cs
- BigInt.cs
- PhysicalFontFamily.cs
- LineVisual.cs
- XmlDictionaryReader.cs
- GenericUriParser.cs
- InstancePersistence.cs
- EdgeProfileValidation.cs
- AssemblyBuilder.cs
- FaultDescriptionCollection.cs
- ImageList.cs
- RemotingSurrogateSelector.cs
- RangeValuePattern.cs
- dataSvcMapFileLoader.cs
- ProjectionCamera.cs
- CodeConditionStatement.cs
- CreatingCookieEventArgs.cs
- GeneralTransform3DTo2DTo3D.cs