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
- LoadWorkflowByKeyAsyncResult.cs
- TypeBrowser.xaml.cs
- EventLogPropertySelector.cs
- ReadonlyMessageFilter.cs
- SparseMemoryStream.cs
- DefaultMemberAttribute.cs
- EventRouteFactory.cs
- BitmapEffectDrawing.cs
- BasicBrowserDialog.designer.cs
- SchemaDeclBase.cs
- DeferrableContentConverter.cs
- ListItemCollection.cs
- AppSettingsSection.cs
- ApplicationException.cs
- InputScopeNameConverter.cs
- ObjectContext.cs
- DispatchWrapper.cs
- DbDataSourceEnumerator.cs
- LambdaCompiler.Binary.cs
- ToolStripButton.cs
- OutputCacheProfileCollection.cs
- MsdtcWrapper.cs
- DataProtection.cs
- DbConnectionHelper.cs
- StateDesignerConnector.cs
- WsdlWriter.cs
- OdbcEnvironment.cs
- SubstitutionList.cs
- DynamicExpression.cs
- X509Certificate2Collection.cs
- DataStreamFromComStream.cs
- CharacterString.cs
- Ref.cs
- ObjectAnimationBase.cs
- XmlTextReaderImpl.cs
- WindowsSecurityToken.cs
- CodeIdentifiers.cs
- BinaryNode.cs
- HMACSHA1.cs
- UnsafeNativeMethodsTablet.cs
- ViewManager.cs
- ComplexPropertyEntry.cs
- EventArgs.cs
- DrawingAttributes.cs
- AssociationTypeEmitter.cs
- RelationshipNavigation.cs
- WebBrowsableAttribute.cs
- FixedFindEngine.cs
- WindowsRichEditRange.cs
- ObjectRef.cs
- KerberosSecurityTokenAuthenticator.cs
- DatatypeImplementation.cs
- RichTextBox.cs
- CommandBinding.cs
- TaskHelper.cs
- TextTrailingWordEllipsis.cs
- RewritingSimplifier.cs
- AccessDataSource.cs
- ReadOnlyDataSource.cs
- ListView.cs
- WebEvents.cs
- cookiecollection.cs
- BooleanStorage.cs
- RegistryKey.cs
- ContentValidator.cs
- DataControlCommands.cs
- EventLogger.cs
- BrushValueSerializer.cs
- ProviderException.cs
- CanonicalFontFamilyReference.cs
- PopupControlService.cs
- CatalogZoneBase.cs
- SqlConnectionManager.cs
- GeneratedView.cs
- CachedPathData.cs
- OdbcParameter.cs
- EventLogPermissionAttribute.cs
- OdbcCommandBuilder.cs
- TagMapInfo.cs
- MergablePropertyAttribute.cs
- ReachDocumentPageSerializer.cs
- AnnotationStore.cs
- SpellerHighlightLayer.cs
- DataDocumentXPathNavigator.cs
- NetworkAddressChange.cs
- EntityDataSourceConfigureObjectContext.cs
- CompilerGlobalScopeAttribute.cs
- ShaderEffect.cs
- WebSysDefaultValueAttribute.cs
- OleStrCAMarshaler.cs
- Matrix3DConverter.cs
- COAUTHIDENTITY.cs
- SqlTriggerAttribute.cs
- ServiceOperationDetailViewControl.cs
- FontNamesConverter.cs
- BindableAttribute.cs
- PlatformCulture.cs
- Cursors.cs
- TypeNameConverter.cs
- Sorting.cs