< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Dispatcher.ServiceThrottle
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/ServiceThrottle.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 111
Coverable lines: 111
Total lines: 423
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 56
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/ServiceThrottle.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Threading.Tasks;
 6using CoreWCF.Runtime;
 7
 8namespace CoreWCF.Dispatcher
 9{
 10    public sealed class ServiceThrottle
 11    {
 12        internal const int DefaultMaxConcurrentCalls = 16;
 13        internal const int DefaultMaxConcurrentSessions = 100;
 014        internal static int DefaultMaxConcurrentCallsCpuCount = DefaultMaxConcurrentCalls * Environment.ProcessorCount;
 015        internal static int DefaultMaxConcurrentSessionsCpuCount = DefaultMaxConcurrentSessions * Environment.ProcessorC
 16
 17        private FlowThrottle _calls;
 18        private FlowThrottle _sessions;
 19        private QuotaThrottle _dynamic;
 20        private FlowThrottle _instanceContexts;
 21
 22        private readonly ServiceHostBase _host;
 23
 024        internal ServiceThrottle(ServiceHostBase host)
 25        {
 026            if (!((host != null)))
 27            {
 28                Fx.Assert("ServiceThrottle.ServiceThrottle: (host != null)");
 029                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(host));
 30            }
 031            _host = host;
 032            MaxConcurrentCalls = DefaultMaxConcurrentCallsCpuCount;
 033            MaxConcurrentSessions = DefaultMaxConcurrentSessionsCpuCount;
 34
 035            IsActive = true;
 036        }
 37
 38        private FlowThrottle Calls
 39        {
 40            get
 41            {
 042                if (_calls == null)
 43                {
 044                    lock (ThisLock)
 45                    {
 046                        if (_calls == null)
 47                        {
 048                            FlowThrottle callsFt = new FlowThrottle(DefaultMaxConcurrentCallsCpuCount,
 049                                MaxConcurrentCallsPropertyName, MaxConcurrentCallsConfigName);
 50
 051                            callsFt.SetRatio(RatioCallsToken);
 52
 053                            _calls = callsFt;
 54                        }
 055                    }
 56                }
 57
 058                return _calls;
 59            }
 60        }
 61
 62        private FlowThrottle Sessions
 63        {
 64            get
 65            {
 066                if (_sessions == null)
 67                {
 068                    lock (ThisLock)
 69                    {
 070                        if (_sessions == null)
 71                        {
 072                            FlowThrottle sessionsFt = new FlowThrottle(DefaultMaxConcurrentSessionsCpuCount,
 073                                MaxConcurrentSessionsPropertyName, MaxConcurrentSessionsConfigName);
 74
 075                            sessionsFt.SetRatio(RatioSessionsToken);
 76
 077                            _sessions = sessionsFt;
 78                        }
 079                    }
 80                }
 81
 082                return _sessions;
 83            }
 84        }
 85
 86        private QuotaThrottle Dynamic
 87        {
 88            get
 89            {
 090                if (_dynamic == null)
 91                {
 092                    lock (ThisLock)
 93                    {
 094                        if (_dynamic == null)
 95                        {
 096                            QuotaThrottle dynamicQt = new QuotaThrottle(new object())
 097                            {
 098                                Owner = "ServiceHost"
 099                            };
 100
 0101                            _dynamic = dynamicQt;
 102                        }
 0103                    }
 104                }
 105
 0106                UpdateIsActive();
 0107                return _dynamic;
 108            }
 109        }
 110
 111        internal int ManualFlowControlLimit
 112        {
 0113            get { return Dynamic.Limit; }
 0114            set { Dynamic.SetLimit(value); }
 115        }
 116
 117        private const string MaxConcurrentCallsPropertyName = "MaxConcurrentCalls";
 118        private const string MaxConcurrentCallsConfigName = "maxConcurrentCalls";
 119        public int MaxConcurrentCalls
 120        {
 0121            get { return Calls.Capacity; }
 122            set
 123            {
 0124                ThrowIfClosedOrOpened(MaxConcurrentCallsPropertyName);
 0125                Calls.Capacity = value;
 0126                UpdateIsActive();
 127                //if (null != this.servicePerformanceCounters)
 128                //{
 129                //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.Calls
 130                //}
 0131            }
 132        }
 133
 134        private const string MaxConcurrentSessionsPropertyName = "MaxConcurrentSessions";
 135        private const string MaxConcurrentSessionsConfigName = "maxConcurrentSessions";
 136        public int MaxConcurrentSessions
 137        {
 0138            get { return Sessions.Capacity; }
 139            set
 140            {
 0141                ThrowIfClosedOrOpened(MaxConcurrentSessionsPropertyName);
 0142                Sessions.Capacity = value;
 0143                UpdateIsActive();
 144                //if (null != this.servicePerformanceCounters)
 145                //{
 146                //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.Sessi
 147                //}
 0148            }
 149        }
 150
 151        private const string MaxConcurrentInstancesPropertyName = "MaxConcurrentInstances";
 152        private const string MaxConcurrentInstancesConfigName = "maxConcurrentInstances";
 153        public int MaxConcurrentInstances
 154        {
 0155            get { return InstanceContexts.Capacity; }
 156            set
 157            {
 0158                ThrowIfClosedOrOpened(MaxConcurrentInstancesPropertyName);
 0159                InstanceContexts.Capacity = value;
 0160                UpdateIsActive();
 161                //if (null != this.servicePerformanceCounters)
 162                //{
 163                //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.Insta
 164                //}
 0165            }
 166        }
 167
 168        private FlowThrottle InstanceContexts
 169        {
 170            get
 171            {
 0172                if (_instanceContexts == null)
 173                {
 0174                    lock (ThisLock)
 175                    {
 0176                        if (_instanceContexts == null)
 177                        {
 0178                            FlowThrottle instanceContextsFt = new FlowThrottle(int.MaxValue,
 0179                                                                     MaxConcurrentInstancesPropertyName, MaxConcurrentIn
 0180                            instanceContextsFt.SetRatio(RatioInstancesToken);
 181
 182                            //if (this.servicePerformanceCounters != null)
 183                            //{
 184                            //    InitializeInstancePerfCounterSettings(instanceContextsFt);
 185                            //}
 186
 0187                            _instanceContexts = instanceContextsFt;
 188                        }
 0189                    }
 190                }
 191
 0192                return _instanceContexts;
 193            }
 194        }
 195
 0196        internal bool IsActive { get; private set; }
 197
 0198        internal object ThisLock { get; } = new object();
 199
 200        //internal void SetServicePerformanceCounters(ServicePerformanceCountersBase counters)
 201        //{
 202        //    this.servicePerformanceCounters = counters;
 203        //    //instance throttle is created through the behavior, set the perf counter callbacks if initialized
 204        //    if (_instanceContexts != null)
 205        //    {
 206        //        InitializeInstancePerfCounterSettings(_instanceContexts);
 207        //    }
 208
 209        //    //this.calls and this.sessions throttles are created by the constructor. Set the perf counter callbacks
 210        //    InitializeCallsPerfCounterSettings();
 211        //    InitializeSessionsPerfCounterSettings();
 212        //}
 213
 214        //void InitializeInstancePerfCounterSettings(FlowThrottle instanceContextsFt)
 215        //{
 216        //    Fx.Assert(instanceContextsFt != null, "Expect instanceContext to be initialized");
 217        //    Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
 218        //    instanceContextsFt.SetAcquired(AcquiredInstancesToken);
 219        //    instanceContextsFt.SetReleased(ReleasedInstancesToken);
 220        //    instanceContextsFt.SetRatio(RatioInstancesToken);
 221        //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.InstancesPerc
 222        //}
 223
 224        //void InitializeCallsPerfCounterSettings()
 225        //{
 226        //    Fx.Assert(_calls != null, "Expect calls to be initialized");
 227        //    Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
 228        //    _calls.SetAcquired(AcquiredCallsToken);
 229        //    _calls.SetReleased(ReleasedCallsToken);
 230        //    _calls.SetRatio(RatioCallsToken);
 231        //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.CallsPercentM
 232        //}
 233
 234        //void InitializeSessionsPerfCounterSettings()
 235        //{
 236        //    Fx.Assert(_sessions != null, "Expect sessions to be initialized");
 237        //    Fx.Assert(this.servicePerformanceCounters != null, "expect servicePerformanceCounters to be set");
 238        //    _sessions.SetAcquired(AcquiredSessionsToken);
 239        //    _sessions.SetReleased(ReleasedSessionsToken);
 240        //    _sessions.SetRatio(RatioSessionsToken);
 241        //    this.servicePerformanceCounters.SetThrottleBase((int)ServicePerformanceCounters.PerfCounters.SessionsPerce
 242        //}
 243
 244        private async Task PrivateAcquireCallAsync()
 245        {
 0246            if (_calls != null)
 247            {
 0248                await _calls.AcquireAsync();
 249            }
 0250        }
 251
 252        //bool PrivateAcquireSessionListenerHandler(ListenerHandler listener)
 253        //{
 254        //    if ((_sessions != null) && (listener.Channel != null) && (listener.Channel.Throttle == null))
 255        //    {
 256        //        listener.Channel.Throttle = this;
 257        //        return _sessions.Acquire(listener);
 258        //    }
 259        //    else
 260        //    {
 261        //        return true;
 262        //    }
 263        //}
 264
 265        private async Task PrivateAcquireSessionAsync()
 266        {
 0267            if (_sessions != null)
 268            {
 0269                await _sessions.AcquireAsync();
 270            }
 0271        }
 272
 273        private async Task PrivateAcquireDynamicAsync()
 274        {
 0275            if (_dynamic != null)
 276            {
 0277                await _dynamic.AcquireAsync();
 278            }
 0279        }
 280
 281        private async Task PrivateAcquireInstanceContextAsync(ChannelHandler channel)
 282        {
 0283            if ((_instanceContexts != null) && (channel.InstanceContext == null))
 284            {
 0285                channel.InstanceContextServiceThrottle = this;
 0286                await _instanceContexts.AcquireAsync();
 287            }
 0288        }
 289
 290        internal Task AcquireCallAsync()
 291        {
 0292            return PrivateAcquireCallAsync();
 293        }
 294
 295        internal async Task AcquireInstanceContextAndDynamicAsync(ChannelHandler channel, bool acquireInstanceContextThr
 296        {
 297            // TODO: Lock removed. This code looks like it should be safe to execute without the lock. Need to verify.
 0298            if (acquireInstanceContextThrottle)
 299            {
 0300                await PrivateAcquireInstanceContextAsync(channel);
 301            }
 302
 0303            await PrivateAcquireDynamicAsync();
 0304        }
 305
 306        internal Task AcquireSessionAsync()
 307        {
 0308            return PrivateAcquireSessionAsync();
 309        }
 310
 311        internal void DeactivateChannel()
 312        {
 0313            if (IsActive)
 314            {
 0315                if (_sessions != null)
 316                {
 0317                    _sessions.Release();
 318                }
 319            }
 0320        }
 321
 322        internal void DeactivateCall()
 323        {
 0324            if (IsActive)
 325            {
 0326                if (_calls != null)
 327                {
 0328                    _calls.Release();
 329                }
 330            }
 0331        }
 332
 333        internal void DeactivateInstanceContext()
 334        {
 0335            if (IsActive)
 336            {
 0337                if (_instanceContexts != null)
 338                {
 0339                    _instanceContexts.Release();
 340                }
 341            }
 0342        }
 343
 344        internal int IncrementManualFlowControlLimit(int incrementBy)
 345        {
 0346            return Dynamic.IncrementLimit(incrementBy);
 347        }
 348
 349        private void ThrowIfClosedOrOpened(string memberName)
 350        {
 0351            if (_host.State == CommunicationState.Opened)
 352            {
 0353                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.SFx
 354            }
 355            else
 356            {
 0357                _host.ThrowIfClosedOrOpened();
 358            }
 0359        }
 360
 361        private void UpdateIsActive()
 362        {
 0363            IsActive = ((_dynamic != null) ||
 0364                             ((_calls != null) && (_calls.Capacity != int.MaxValue)) ||
 0365                             ((_sessions != null) && (_sessions.Capacity != int.MaxValue)) ||
 0366                             ((_instanceContexts != null) && (_instanceContexts.Capacity != int.MaxValue)));
 0367        }
 368
 369        //internal void AcquiredCallsToken()
 370        //{
 371        //    this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Call
 372        //}
 373
 374        //internal void ReleasedCallsToken()
 375        //{
 376        //    this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Call
 377        //}
 378
 379        internal void RatioCallsToken(int count)
 380        {
 381            //if (TD.ConcurrentCallsRatioIsEnabled())
 382            //{
 383            //    TD.ConcurrentCallsRatio(count, MaxConcurrentCalls);
 384            //}
 0385        }
 386
 387        //internal void AcquiredInstancesToken()
 388        //{
 389        //    this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Inst
 390        //}
 391
 392        //internal void ReleasedInstancesToken()
 393        //{
 394        //    this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Inst
 395        //}
 396
 397        internal void RatioInstancesToken(int count)
 398        {
 399            //if (TD.ConcurrentInstancesRatioIsEnabled())
 400            //{
 401            //    TD.ConcurrentInstancesRatio(count, MaxConcurrentInstances);
 402            //}
 0403        }
 404
 405        //internal void AcquiredSessionsToken()
 406        //{
 407        //    this.servicePerformanceCounters.IncrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Sess
 408        //}
 409
 410        //internal void ReleasedSessionsToken()
 411        //{
 412        //    this.servicePerformanceCounters.DecrementThrottlePercent((int)ServicePerformanceCounters.PerfCounters.Sess
 413        //}
 414
 415        internal void RatioSessionsToken(int count)
 416        {
 417            //if (TD.ConcurrentSessionsRatioIsEnabled())
 418            //{
 419            //    TD.ConcurrentSessionsRatio(count, MaxConcurrentSessions);
 420            //}
 0421        }
 422    }
 423}