158 lines
5.3 KiB
C#
158 lines
5.3 KiB
C#
|
//----------------------------------------------------------------
|
|||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
//----------------------------------------------------------------
|
|||
|
|
|||
|
namespace System.ServiceModel.Routing
|
|||
|
{
|
|||
|
using System;
|
|||
|
using System.Diagnostics.CodeAnalysis;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Runtime;
|
|||
|
using System.ServiceModel.Description;
|
|||
|
using System.ServiceModel.Channels;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Threading;
|
|||
|
|
|||
|
class SessionChannels
|
|||
|
{
|
|||
|
Guid activityID;
|
|||
|
[Fx.Tag.SynchronizationObject]
|
|||
|
Dictionary<RoutingEndpointTrait, IRoutingClient> sessions;
|
|||
|
List<IRoutingClient> sessionList;
|
|||
|
|
|||
|
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "gets called in RoutingService.ctor()")]
|
|||
|
public SessionChannels(Guid activityID)
|
|||
|
{
|
|||
|
this.activityID = activityID;
|
|||
|
this.sessions = new Dictionary<RoutingEndpointTrait, IRoutingClient>();
|
|||
|
this.sessionList = new List<IRoutingClient>();
|
|||
|
}
|
|||
|
|
|||
|
void ChannelFaulted(object sender, EventArgs args)
|
|||
|
{
|
|||
|
FxTrace.Trace.SetAndTraceTransfer(this.activityID, true);
|
|||
|
IRoutingClient client = (IRoutingClient)sender;
|
|||
|
if (TD.RoutingServiceChannelFaultedIsEnabled())
|
|||
|
{
|
|||
|
TD.RoutingServiceChannelFaulted(client.Key.ToString());
|
|||
|
}
|
|||
|
this.AbortChannel(client.Key);
|
|||
|
}
|
|||
|
|
|||
|
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "BeginClose is called by RoutingChannelExtension.AttachService")]
|
|||
|
public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
|
|||
|
{
|
|||
|
List<ICommunicationObject> localClients = null;
|
|||
|
|
|||
|
lock (this.sessions)
|
|||
|
{
|
|||
|
if (this.sessions.Count > 0)
|
|||
|
{
|
|||
|
localClients = this.sessionList.ConvertAll<ICommunicationObject>((client) => (ICommunicationObject)client);
|
|||
|
this.sessionList.Clear();
|
|||
|
this.sessions.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (localClients != null && localClients.Count > 0)
|
|||
|
{
|
|||
|
localClients.ForEach((client) =>
|
|||
|
{
|
|||
|
if (TD.RoutingServiceClosingClientIsEnabled())
|
|||
|
{
|
|||
|
TD.RoutingServiceClosingClient(((IRoutingClient)client).Key.ToString());
|
|||
|
}
|
|||
|
});
|
|||
|
return new CloseCollectionAsyncResult(timeout, callback, state, localClients);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return new CompletedAsyncResult(callback, state);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void EndClose(IAsyncResult asyncResult)
|
|||
|
{
|
|||
|
if (asyncResult is CloseCollectionAsyncResult)
|
|||
|
{
|
|||
|
CloseCollectionAsyncResult.End(asyncResult);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CompletedAsyncResult.End(asyncResult);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal IRoutingClient GetOrCreateClient<TContract>(RoutingEndpointTrait key, RoutingService service, bool impersonating)
|
|||
|
{
|
|||
|
IRoutingClient value;
|
|||
|
lock (this.sessions)
|
|||
|
{
|
|||
|
if (!this.sessions.TryGetValue(key, out value))
|
|||
|
{
|
|||
|
//Create the client here
|
|||
|
value = ClientFactory.Create(key, service, impersonating);
|
|||
|
value.Faulted += ChannelFaulted;
|
|||
|
this.sessions[key] = value;
|
|||
|
sessionList.Add(value);
|
|||
|
}
|
|||
|
}
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
public void AbortAll()
|
|||
|
{
|
|||
|
List<IRoutingClient> clients = new List<IRoutingClient>();
|
|||
|
|
|||
|
lock (this.sessions)
|
|||
|
{
|
|||
|
foreach (IRoutingClient client in this.sessions.Values)
|
|||
|
{
|
|||
|
clients.Add(client);
|
|||
|
}
|
|||
|
this.sessions.Clear();
|
|||
|
this.sessionList.Clear();
|
|||
|
}
|
|||
|
|
|||
|
foreach (IRoutingClient client in clients)
|
|||
|
{
|
|||
|
RoutingUtilities.Abort((ICommunicationObject)client, client.Key);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void AbortChannel(RoutingEndpointTrait key)
|
|||
|
{
|
|||
|
IRoutingClient client;
|
|||
|
lock (this.sessions)
|
|||
|
{
|
|||
|
if (this.sessions.TryGetValue(key, out client))
|
|||
|
{
|
|||
|
this.sessions.Remove(key);
|
|||
|
this.sessionList.Remove(client);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (client != null)
|
|||
|
{
|
|||
|
RoutingUtilities.Abort((ICommunicationObject)client, client.Key);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public IRoutingClient ReleaseChannel()
|
|||
|
{
|
|||
|
IRoutingClient client = null;
|
|||
|
lock (this.sessions)
|
|||
|
{
|
|||
|
int count = this.sessionList.Count;
|
|||
|
if (count > 0)
|
|||
|
{
|
|||
|
client = this.sessionList[count - 1];
|
|||
|
this.sessionList.RemoveAt(count - 1);
|
|||
|
this.sessions.Remove(client.Key);
|
|||
|
}
|
|||
|
}
|
|||
|
return client;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|