e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
174 lines
5.8 KiB
C#
174 lines
5.8 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Dispatcher
|
|
{
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Channels;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.ServiceModel.Diagnostics;
|
|
using System.Threading;
|
|
|
|
class EndpointDispatcherTable
|
|
{
|
|
MessageFilterTable<EndpointDispatcher> filters;
|
|
object thisLock;
|
|
const int optimizationThreshold = 2;
|
|
List<EndpointDispatcher> cachedEndpoints;
|
|
|
|
public EndpointDispatcherTable(object thisLock)
|
|
{
|
|
this.thisLock = thisLock;
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
return ((this.cachedEndpoints != null) ? cachedEndpoints.Count : 0) +
|
|
((this.filters != null) ? this.filters.Count : 0);
|
|
}
|
|
}
|
|
|
|
object ThisLock
|
|
{
|
|
get { return thisLock; }
|
|
}
|
|
|
|
public void AddEndpoint(EndpointDispatcher endpoint)
|
|
{
|
|
lock (ThisLock)
|
|
{
|
|
MessageFilter filter = endpoint.EndpointFilter;
|
|
int priority = endpoint.FilterPriority;
|
|
|
|
if (filters == null)
|
|
{
|
|
if (this.cachedEndpoints == null)
|
|
{
|
|
this.cachedEndpoints = new List<EndpointDispatcher>(optimizationThreshold);
|
|
}
|
|
|
|
if (this.cachedEndpoints.Count < optimizationThreshold)
|
|
{
|
|
this.cachedEndpoints.Add(endpoint);
|
|
}
|
|
else
|
|
{
|
|
filters = new MessageFilterTable<EndpointDispatcher>();
|
|
for (int i = 0; i < this.cachedEndpoints.Count; i++)
|
|
{
|
|
int cachedPriority = cachedEndpoints[i].FilterPriority;
|
|
MessageFilter cachedFilter = cachedEndpoints[i].EndpointFilter;
|
|
filters.Add(cachedFilter, cachedEndpoints[i], cachedPriority);
|
|
}
|
|
filters.Add(filter, endpoint, priority);
|
|
this.cachedEndpoints = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
filters.Add(filter, endpoint, priority);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void RemoveEndpoint(EndpointDispatcher endpoint)
|
|
{
|
|
lock (ThisLock)
|
|
{
|
|
if (filters == null)
|
|
{
|
|
if (cachedEndpoints != null && cachedEndpoints.Contains(endpoint))
|
|
{
|
|
cachedEndpoints.Remove(endpoint);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageFilter filter = endpoint.EndpointFilter;
|
|
filters.Remove(filter);
|
|
}
|
|
}
|
|
}
|
|
|
|
EndpointDispatcher LookupInCache(Message message, out bool addressMatched)
|
|
{
|
|
EndpointDispatcher result = null;
|
|
int priority = int.MinValue;
|
|
bool duplicatePriority = false;
|
|
addressMatched = false;
|
|
|
|
if (this.cachedEndpoints != null && this.cachedEndpoints.Count > 0)
|
|
{
|
|
for (int i = 0; i < this.cachedEndpoints.Count; i++)
|
|
{
|
|
EndpointDispatcher cachedEndpoint = cachedEndpoints[i];
|
|
int cachedPriority = cachedEndpoint.FilterPriority;
|
|
MessageFilter cachedFilter = cachedEndpoint.EndpointFilter;
|
|
|
|
bool matchResult;
|
|
AndMessageFilter andFilter = cachedFilter as AndMessageFilter;
|
|
if (andFilter != null)
|
|
{
|
|
bool addressResult;
|
|
matchResult = andFilter.Match(message, out addressResult);
|
|
addressMatched |= addressResult;
|
|
}
|
|
else
|
|
{
|
|
matchResult = cachedFilter.Match(message);
|
|
}
|
|
|
|
if (matchResult)
|
|
{
|
|
addressMatched = true;
|
|
if (cachedPriority > priority || result == null)
|
|
{
|
|
result = cachedEndpoint;
|
|
priority = cachedPriority;
|
|
duplicatePriority = false;
|
|
}
|
|
else if (cachedPriority == priority && result != null)
|
|
{
|
|
duplicatePriority = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (duplicatePriority)
|
|
{
|
|
throw TraceUtility.ThrowHelperError(new MultipleFilterMatchesException(SR.GetString(SR.FilterMultipleMatches)), message);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public EndpointDispatcher Lookup(Message message, out bool addressMatched)
|
|
{
|
|
EndpointDispatcher data = null;
|
|
|
|
data = LookupInCache(message, out addressMatched);
|
|
|
|
if (data == null)
|
|
{
|
|
lock (ThisLock)
|
|
{
|
|
data = LookupInCache(message, out addressMatched);
|
|
|
|
if (data == null && filters != null)
|
|
{
|
|
filters.GetMatchingValue(message, out data, out addressMatched);
|
|
}
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
}
|
|
}
|