ChannelManagerService.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx35 / System.WorkflowServices / System / Workflow / Runtime / Hosting / ChannelManagerService.cs / 1305376 / ChannelManagerService.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.Workflow.Runtime.Hosting 
{
    using System; 
    using System.Collections.Generic; 
    using System.Collections.Specialized;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Runtime;
    using System.ServiceModel;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Description;
    using System.Workflow.Activities; 
    using System.Workflow.ComponentModel; 

    public sealed class ChannelManagerService : WorkflowRuntimeService 
    {
        const string IdleTimeoutSetting = "idleTimeout";
        const string InfiniteTimeSpanValue = "infinite";
        const string LeaseTimeoutSetting = "leaseTimeout"; 
        const string MaxIdleChannelsPerEndpointSetting = "maxIdleChannelsPerEndpoint";
 
        ChannelManager channelManager; 

        bool closed; 
        IList codeEndpoints;
        ChannelPoolSettings settings;

        public ChannelManagerService() 
            : this(new ChannelPoolSettings(), new List())
        { 
        } 

        public ChannelManagerService(ChannelPoolSettings settings) 
            : this(settings, new List())
        {
        }
 
        public ChannelManagerService(IList endpoints)
            : this(new ChannelPoolSettings(), endpoints) 
        { 
        }
 
        public ChannelManagerService(ChannelPoolSettings settings, IList endpoints)
        {
            if (settings == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("settings");
            } 
 
            if (endpoints == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoints");
            }

            this.settings = settings; 
            this.codeEndpoints = endpoints;
        } 
 
        public ChannelManagerService(NameValueCollection parameters)
        { 
            if (parameters == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
            } 

            ChannelPoolSettings channelPoolSettings = new ChannelPoolSettings(); 
 
            foreach (string key in parameters.Keys)
            { 
                if (string.IsNullOrEmpty(key))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                        SR2.GetString(SR2.Error_UnknownConfigurationParameter, key), "parameters"); 
                }
                else if (key.Equals(ChannelManagerService.IdleTimeoutSetting, StringComparison.OrdinalIgnoreCase)) 
                { 
                    try
                    { 
                        channelPoolSettings.IdleTimeout =
                            ConvertToTimeSpan(parameters[ChannelManagerService.IdleTimeoutSetting]);
                    }
                    catch (FormatException ex) 
                    {
                        ArgumentException exception = new ArgumentException( 
                            SR2.GetString(SR2.Error_InvalidIdleTimeout, parameters[ChannelManagerService.IdleTimeoutSetting]), 
                            "parameters",
                            ex); 

                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
                    }
                } 
                else if (key.Equals(ChannelManagerService.LeaseTimeoutSetting, StringComparison.OrdinalIgnoreCase))
                { 
                    try 
                    {
                        channelPoolSettings.LeaseTimeout = 
                            ConvertToTimeSpan(parameters[ChannelManagerService.LeaseTimeoutSetting]);
                    }
                    catch (FormatException ex)
                    { 
                        ArgumentException exception = new ArgumentException(
                            SR2.GetString(SR2.Error_InvalidLeaseTimeout, parameters[ChannelManagerService.LeaseTimeoutSetting]), 
                            "parameters", 
                            ex);
 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
                    }
                }
                else if (key.Equals(ChannelManagerService.MaxIdleChannelsPerEndpointSetting, StringComparison.OrdinalIgnoreCase)) 
                {
                    try 
                    { 
                        channelPoolSettings.MaxOutboundChannelsPerEndpoint =
                            Convert.ToInt32(parameters[ChannelManagerService.MaxIdleChannelsPerEndpointSetting], System.Globalization.CultureInfo.CurrentCulture); 
                    }
                    catch (FormatException ex)
                    {
                        ArgumentException exception = new ArgumentException( 
                            SR2.GetString(SR2.Error_InvalidMaxIdleChannelsPerEndpoint, parameters[ChannelManagerService.MaxIdleChannelsPerEndpointSetting]),
                            "parameters", 
                            ex); 

                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception); 
                    }
                }
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                        SR2.GetString(SR2.Error_UnknownConfigurationParameter, key), "parameters"); 
                } 
            }
 
            this.settings = channelPoolSettings;
            this.codeEndpoints = new List();
        }
 
        protected internal override void Start()
        { 
            base.Start(); 

            this.channelManager = new ChannelManager(this.settings, this.codeEndpoints); 
            this.closed = false;
        }

        protected internal override void Stop() 
        {
            base.Stop(); 
 
            if (!this.closed && this.channelManager != null)
            { 
                this.channelManager.Close();
            }

            this.closed = true; 
        }
 
        internal static void ApplyLogicalChannelContext(LogicalChannel logicalChannel) 
        {
            Fx.Assert(OperationContext.Current != null, "Can be called within a valid OperationContext Scope"); 

            WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0,
                "ChannelManagerService: updating context associated with logical channel {0}",
                logicalChannel.InstanceId); 

            if (logicalChannel.Context != null) 
            { 
                new ContextMessageProperty(logicalChannel.Context).AddOrReplaceInMessageProperties(OperationContext.Current.OutgoingMessageProperties);
            } 
        }

        internal static TransientChannelTicket CreateTransientChannel(LogicalChannel logicalChannel)
        { 
            DiagnosticUtility.DebugAssert(logicalChannel != null, "logical channel cannot be null");
 
            ChannelFactory factory = null; 
            IChannel channel = null;
            bool channelOpened = false; 

            try
            {
                factory = ChannelManagerHelpers.CreateChannelFactory(logicalChannel.ConfigurationName, logicalChannel.ContractType); 
                channel = ChannelManagerHelpers.CreateChannel(logicalChannel.ContractType, factory, logicalChannel.CustomAddress);
                channelOpened = true; 
            } 
            finally
            { 
                if (!channelOpened)
                {
                    if (channel != null)
                    { 
                        ChannelManagerHelpers.CloseCommunicationObject(channel);
                    } 
                    if (factory != null) 
                    {
                        ChannelManagerHelpers.CloseCommunicationObject(factory); 
                    }
                }
            }
 
            return new TransientChannelTicket(channel, factory);
        } 
 
        internal static ChannelTicket Take(ActivityExecutionContext executionContext, Guid workflowId, LogicalChannel logicalChannel)
        { 
            if (executionContext == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
            } 

            if (workflowId == Guid.Empty) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
                    SR2.GetString(SR2.Error_Cache_InvalidWorkflowId)); 
            }

            if (logicalChannel == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel");
            } 
 
            ChannelManagerService channelManager = executionContext.GetService();
 
            ChannelTicket channel;
            if (channelManager != null)
            {
                channel = channelManager.TakeChannel(workflowId, logicalChannel); 
            }
            else 
            { 
                channel = ChannelManagerService.CreateTransientChannel(logicalChannel);
            } 

            return channel;
        }
 
        internal static void UpdateLogicalChannelContext(LogicalChannel logicalChannel)
        { 
            Fx.Assert(OperationContext.Current != null, "Can be called from valid OperationContextScope"); 

            WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0, 
                "ChannelManagerService: updating context associated with logical channel {0}",
                logicalChannel.InstanceId);

            ContextMessageProperty contextMessageProperty; 
            MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
 
            if (properties != null && ContextMessageProperty.TryGet(properties, out contextMessageProperty)) 
            {
                logicalChannel.Context = contextMessageProperty.Context; 
            }
        }

        internal void ReturnChannel(PooledChannelTicket pooledChannel) 
        {
            DiagnosticUtility.DebugAssert(pooledChannel != null, "pooled channel cannot be null"); 
            if (pooledChannel == null) 
            {
                return; 
            }

            WorkflowTrace.Host.TraceEvent(
                TraceEventType.Information, 0, 
                "ChannelManagerService: return channel for workflow instance {0}, logical channel {1}",
                new object[] { pooledChannel.WorkflowId, pooledChannel.LogicalChannelId }); 
 
            this.channelManager.ReturnChannel(pooledChannel.ChannelPoolKey, pooledChannel.PooledChannel);
        } 

        internal PooledChannelTicket TakeChannel(Guid workflowId, LogicalChannel logicalChannel)
        {
            if (this.closed) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel_ServiceStopped, logicalChannel.ConfigurationName, logicalChannel.CustomAddress))); 
            }
 
            if (workflowId == Guid.Empty)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
                    SR2.GetString(SR2.Error_Cache_InvalidWorkflowId)); 
            }
 
            if (logicalChannel == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel"); 
            }

            WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "ChannelManagerService: get channel for workflow instance {0}, logical channel {1}", new object[] { workflowId, logicalChannel.InstanceId });
 
            string endpointName = logicalChannel.ConfigurationName;
            Type contractType = logicalChannel.ContractType; 
            string customAddress = logicalChannel.CustomAddress; 

            ChannelPoolKey channelKey; 
            ChannelManager.PooledChannel channel = this.channelManager.TakeChannel(endpointName, contractType, customAddress, out channelKey);
            if (channel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel, logicalChannel.ConfigurationName, logicalChannel.CustomAddress)));
            } 
 
            PooledChannelTicket pooledChannel = new PooledChannelTicket(this, channel, channelKey, workflowId, logicalChannel.InstanceId);
            return pooledChannel; 
        }

        TimeSpan ConvertToTimeSpan(string value)
        { 
            if (string.Equals(value, ChannelManagerService.InfiniteTimeSpanValue, StringComparison.OrdinalIgnoreCase))
            { 
                return TimeSpan.MaxValue; 
            }
 
            return TimeSpan.Parse(value, CultureInfo.InvariantCulture);
        }

        internal abstract class ChannelTicket : IDisposable 
        {
            bool disposed; 
 
            protected ChannelTicket()
            { 
            }

            public abstract IChannel Channel
            { 
                get;
            } 
 
            public void Dispose()
            { 
                if (!this.disposed)
                {
                    this.disposed = true;
                    this.Close(); 
                }
            } 
 
            protected virtual void Close()
            { 
            }
        }

        internal class PooledChannelTicket : ChannelTicket 
        {
            ChannelManager.PooledChannel channel; 
            ChannelPoolKey channelPoolKey; 
            Guid logicalChannelId;
 
            ChannelManagerService service;
            Guid workflowId;

            public PooledChannelTicket(ChannelManagerService service, ChannelManager.PooledChannel channel, ChannelPoolKey channelPoolKey, Guid workflowId, Guid logicalChannelId) 
                : base()
            { 
                this.service = service; 
                this.channel = channel;
                this.channelPoolKey = channelPoolKey; 
                this.workflowId = workflowId;
                this.logicalChannelId = logicalChannelId;
            }
 
            public override IChannel Channel
            { 
                get 
                {
                    return this.channel.InnerChannel; 
                }
            }

            internal ChannelPoolKey ChannelPoolKey 
            {
                get 
                { 
                    return this.channelPoolKey;
                } 
            }

            internal Guid LogicalChannelId
            { 
                get
                { 
                    return this.logicalChannelId; 
                }
            } 

            internal ChannelManager.PooledChannel PooledChannel
            {
                get 
                {
                    return this.channel; 
                } 
            }
 
            internal Guid WorkflowId
            {
                get
                { 
                    return this.workflowId;
                } 
            } 

            protected override void Close() 
            {
                DiagnosticUtility.DebugAssert(this.channel != null, "channel has been closed already.");
                if (this.channel != null)
                { 
                    this.service.ReturnChannel(this);
                    this.channel = null; 
                } 
            }
        } 

        internal class TransientChannelTicket : ChannelTicket
        {
            IChannel channel; 
            ChannelFactory factory;
 
            public TransientChannelTicket(IChannel channel, ChannelFactory factory) 
                : base()
            { 
                this.channel = channel;
                this.factory = factory;
            }
 
            public override IChannel Channel
            { 
                get 
                {
                    return this.channel; 
                }
            }

            protected override void Close() 
            {
                if (this.channel != null) 
                { 
                    ChannelManagerHelpers.CloseCommunicationObject(this.channel);
                    this.channel = null; 
                }
                if (this.factory != null)
                {
                    ChannelManagerHelpers.CloseCommunicationObject(this.factory); 
                    this.factory = null;
                } 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK