Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / xsp / System / Web / RequestQueue.cs / 1 / RequestQueue.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- // // Request Queue // queues up the requests to avoid thread pool starvation, // making sure that there are always available threads to process requests // namespace System.Web { using System.Threading; using System.Collections; using System.Web.Util; using System.Web.Hosting; using System.Web.Configuration; internal class RequestQueue { // configuration params private int _minExternFreeThreads; private int _minLocalFreeThreads; private int _queueLimit; private TimeSpan _clientConnectedTime; private bool _iis6; // two queues -- one for local requests, one for external private Queue _localQueue = new Queue(); private Queue _externQueue = new Queue(); // total count private int _count; // work items queued to pick up new work private WaitCallback _workItemCallback; private int _workItemCount; private const int _workItemLimit = 2; private bool _draining; // timer to drain the queue private readonly TimeSpan _timerPeriod = new TimeSpan(0, 0, 10); // 10 seconds private Timer _timer; // helpers private static bool IsLocal(HttpWorkerRequest wr) { String remoteAddress = wr.GetRemoteAddress(); // check if localhost if (remoteAddress == "127.0.0.1" || remoteAddress == "::1") return true; // if unknown, assume not local if (String.IsNullOrEmpty(remoteAddress)) return false; // compare with local address if (remoteAddress == wr.GetLocalAddress()) return true; return false; } private void QueueRequest(HttpWorkerRequest wr, bool isLocal) { lock (this) { if (isLocal) { _localQueue.Enqueue(wr); } else { _externQueue.Enqueue(wr); } _count++; } PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_IN_APPLICATION_QUEUE); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Information, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_REQ_QUEUED, wr); } private HttpWorkerRequest DequeueRequest(bool localOnly) { HttpWorkerRequest wr = null; while (_count > 0) { lock (this) { if (_localQueue.Count > 0) { wr = (HttpWorkerRequest)_localQueue.Dequeue(); _count--; } else if (!localOnly && _externQueue.Count > 0) { wr = (HttpWorkerRequest)_externQueue.Dequeue(); _count--; } } if (wr == null) { break; } else { PerfCounters.DecrementGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); PerfCounters.DecrementCounter(AppPerfCounter.REQUESTS_IN_APPLICATION_QUEUE); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Information, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_REQ_DEQUEUED, wr); if (!CheckClientConnected(wr)) { HttpRuntime.RejectRequestNow(wr, true); wr = null; PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_DISCONNECTED); PerfCounters.IncrementCounter(AppPerfCounter.APP_REQUEST_DISCONNECTED); } else { break; } } } return wr; } // This method will check to see if the client is still connected. // The checks are only done if it's an in-proc Isapi request AND the request has been waiting // more than the configured clientConenctedCheck time. private bool CheckClientConnected(HttpWorkerRequest wr) { if (DateTime.UtcNow - wr.GetStartTime() > _clientConnectedTime) return wr.IsClientConnected(); else return true; } // ctor internal RequestQueue(int minExternFreeThreads, int minLocalFreeThreads, int queueLimit, TimeSpan clientConnectedTime) { _minExternFreeThreads = minExternFreeThreads; _minLocalFreeThreads = minLocalFreeThreads; _queueLimit = queueLimit; _clientConnectedTime = clientConnectedTime; _workItemCallback = new WaitCallback(this.WorkItemCallback); _timer = new Timer(new TimerCallback(this.TimerCompletionCallback), null, _timerPeriod, _timerPeriod); _iis6 = HostingEnvironment.IsUnderIIS6Process; // set the minimum number of requests that must be executing in order to detect a deadlock int maxWorkerThreads, maxIoThreads; ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIoThreads); UnsafeNativeMethods.SetMinRequestsExecutingToDetectDeadlock(maxWorkerThreads - minExternFreeThreads); } // method called from HttpRuntime for incoming requests internal HttpWorkerRequest GetRequestToExecute(HttpWorkerRequest wr) { int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); int freeThreads; if (_iis6) freeThreads = workerThreads; // ignore IO threads to avoid starvation from Indigo TCP requests else freeThreads = (ioThreads > workerThreads) ? workerThreads : ioThreads; // fast path when there are threads available and nothing queued if (freeThreads >= _minExternFreeThreads && _count == 0) return wr; bool isLocal = IsLocal(wr); // fast path when there are threads for local requests available and nothing queued if (isLocal && freeThreads >= _minLocalFreeThreads && _count == 0) return wr; // reject if queue limit exceeded if (_count >= _queueLimit) { HttpRuntime.RejectRequestNow(wr, false); return null; } // can't execute the current request on the current thread -- need to queue QueueRequest(wr, isLocal); // maybe can execute a request previously queued if (freeThreads >= _minExternFreeThreads) { wr = DequeueRequest(false); // enough threads to process even external requests } else if (freeThreads >= _minLocalFreeThreads) { wr = DequeueRequest(true); // enough threads to process only local requests } else { wr = null; // not enough threads -> do nothing on this thread ScheduleMoreWorkIfNeeded(); // try to schedule to worker thread } return wr; } // method called from HttpRuntime at the end of request internal void ScheduleMoreWorkIfNeeded() { // too late for more work if draining if (_draining) return; // is queue empty? if (_count == 0) return; // already scheduled enough work items if (_workItemCount >= _workItemLimit) return; // enough worker threads? int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); if (workerThreads < _minLocalFreeThreads) return; // queue the work item Interlocked.Increment(ref _workItemCount); ThreadPool.QueueUserWorkItem(_workItemCallback); } // is empty property internal bool IsEmpty { get { return (_count == 0); } } // method called to pick up more work private void WorkItemCallback(Object state) { Interlocked.Decrement(ref _workItemCount); // too late for more work if draining if (_draining) return; // is queue empty? if (_count == 0) return; int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); // not enough worker threads to do anything if (workerThreads < _minLocalFreeThreads) return; // pick up request from the queue HttpWorkerRequest wr = DequeueRequest(workerThreads < _minExternFreeThreads); if (wr == null) return; // let another work item through before processing the request ScheduleMoreWorkIfNeeded(); // call the runtime to process request HttpRuntime.ProcessRequestNow(wr); } // periodic timer to pick up more work private void TimerCompletionCallback(Object state) { ScheduleMoreWorkIfNeeded(); } // reject all requests internal void Drain() { // set flag before killing timer to shorten the code path // in the callback after the timer is disposed _draining = true; // stop the timer if (_timer != null) { ((IDisposable)_timer).Dispose(); _timer = null; } // wait for all work items to finish while (_workItemCount > 0) Thread.Sleep(100); // is queue empty? if (_count == 0) return; // reject the remaining requests for (;;) { HttpWorkerRequest wr = DequeueRequest(false); if (wr == null) break; HttpRuntime.RejectRequestNow(wr, false); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- // // Request Queue // queues up the requests to avoid thread pool starvation, // making sure that there are always available threads to process requests // namespace System.Web { using System.Threading; using System.Collections; using System.Web.Util; using System.Web.Hosting; using System.Web.Configuration; internal class RequestQueue { // configuration params private int _minExternFreeThreads; private int _minLocalFreeThreads; private int _queueLimit; private TimeSpan _clientConnectedTime; private bool _iis6; // two queues -- one for local requests, one for external private Queue _localQueue = new Queue(); private Queue _externQueue = new Queue(); // total count private int _count; // work items queued to pick up new work private WaitCallback _workItemCallback; private int _workItemCount; private const int _workItemLimit = 2; private bool _draining; // timer to drain the queue private readonly TimeSpan _timerPeriod = new TimeSpan(0, 0, 10); // 10 seconds private Timer _timer; // helpers private static bool IsLocal(HttpWorkerRequest wr) { String remoteAddress = wr.GetRemoteAddress(); // check if localhost if (remoteAddress == "127.0.0.1" || remoteAddress == "::1") return true; // if unknown, assume not local if (String.IsNullOrEmpty(remoteAddress)) return false; // compare with local address if (remoteAddress == wr.GetLocalAddress()) return true; return false; } private void QueueRequest(HttpWorkerRequest wr, bool isLocal) { lock (this) { if (isLocal) { _localQueue.Enqueue(wr); } else { _externQueue.Enqueue(wr); } _count++; } PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_IN_APPLICATION_QUEUE); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Information, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_REQ_QUEUED, wr); } private HttpWorkerRequest DequeueRequest(bool localOnly) { HttpWorkerRequest wr = null; while (_count > 0) { lock (this) { if (_localQueue.Count > 0) { wr = (HttpWorkerRequest)_localQueue.Dequeue(); _count--; } else if (!localOnly && _externQueue.Count > 0) { wr = (HttpWorkerRequest)_externQueue.Dequeue(); _count--; } } if (wr == null) { break; } else { PerfCounters.DecrementGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); PerfCounters.DecrementCounter(AppPerfCounter.REQUESTS_IN_APPLICATION_QUEUE); if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Information, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_REQ_DEQUEUED, wr); if (!CheckClientConnected(wr)) { HttpRuntime.RejectRequestNow(wr, true); wr = null; PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.REQUESTS_DISCONNECTED); PerfCounters.IncrementCounter(AppPerfCounter.APP_REQUEST_DISCONNECTED); } else { break; } } } return wr; } // This method will check to see if the client is still connected. // The checks are only done if it's an in-proc Isapi request AND the request has been waiting // more than the configured clientConenctedCheck time. private bool CheckClientConnected(HttpWorkerRequest wr) { if (DateTime.UtcNow - wr.GetStartTime() > _clientConnectedTime) return wr.IsClientConnected(); else return true; } // ctor internal RequestQueue(int minExternFreeThreads, int minLocalFreeThreads, int queueLimit, TimeSpan clientConnectedTime) { _minExternFreeThreads = minExternFreeThreads; _minLocalFreeThreads = minLocalFreeThreads; _queueLimit = queueLimit; _clientConnectedTime = clientConnectedTime; _workItemCallback = new WaitCallback(this.WorkItemCallback); _timer = new Timer(new TimerCallback(this.TimerCompletionCallback), null, _timerPeriod, _timerPeriod); _iis6 = HostingEnvironment.IsUnderIIS6Process; // set the minimum number of requests that must be executing in order to detect a deadlock int maxWorkerThreads, maxIoThreads; ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIoThreads); UnsafeNativeMethods.SetMinRequestsExecutingToDetectDeadlock(maxWorkerThreads - minExternFreeThreads); } // method called from HttpRuntime for incoming requests internal HttpWorkerRequest GetRequestToExecute(HttpWorkerRequest wr) { int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); int freeThreads; if (_iis6) freeThreads = workerThreads; // ignore IO threads to avoid starvation from Indigo TCP requests else freeThreads = (ioThreads > workerThreads) ? workerThreads : ioThreads; // fast path when there are threads available and nothing queued if (freeThreads >= _minExternFreeThreads && _count == 0) return wr; bool isLocal = IsLocal(wr); // fast path when there are threads for local requests available and nothing queued if (isLocal && freeThreads >= _minLocalFreeThreads && _count == 0) return wr; // reject if queue limit exceeded if (_count >= _queueLimit) { HttpRuntime.RejectRequestNow(wr, false); return null; } // can't execute the current request on the current thread -- need to queue QueueRequest(wr, isLocal); // maybe can execute a request previously queued if (freeThreads >= _minExternFreeThreads) { wr = DequeueRequest(false); // enough threads to process even external requests } else if (freeThreads >= _minLocalFreeThreads) { wr = DequeueRequest(true); // enough threads to process only local requests } else { wr = null; // not enough threads -> do nothing on this thread ScheduleMoreWorkIfNeeded(); // try to schedule to worker thread } return wr; } // method called from HttpRuntime at the end of request internal void ScheduleMoreWorkIfNeeded() { // too late for more work if draining if (_draining) return; // is queue empty? if (_count == 0) return; // already scheduled enough work items if (_workItemCount >= _workItemLimit) return; // enough worker threads? int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); if (workerThreads < _minLocalFreeThreads) return; // queue the work item Interlocked.Increment(ref _workItemCount); ThreadPool.QueueUserWorkItem(_workItemCallback); } // is empty property internal bool IsEmpty { get { return (_count == 0); } } // method called to pick up more work private void WorkItemCallback(Object state) { Interlocked.Decrement(ref _workItemCount); // too late for more work if draining if (_draining) return; // is queue empty? if (_count == 0) return; int workerThreads, ioThreads; ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads); // not enough worker threads to do anything if (workerThreads < _minLocalFreeThreads) return; // pick up request from the queue HttpWorkerRequest wr = DequeueRequest(workerThreads < _minExternFreeThreads); if (wr == null) return; // let another work item through before processing the request ScheduleMoreWorkIfNeeded(); // call the runtime to process request HttpRuntime.ProcessRequestNow(wr); } // periodic timer to pick up more work private void TimerCompletionCallback(Object state) { ScheduleMoreWorkIfNeeded(); } // reject all requests internal void Drain() { // set flag before killing timer to shorten the code path // in the callback after the timer is disposed _draining = true; // stop the timer if (_timer != null) { ((IDisposable)_timer).Dispose(); _timer = null; } // wait for all work items to finish while (_workItemCount > 0) Thread.Sleep(100); // is queue empty? if (_count == 0) return; // reject the remaining requests for (;;) { HttpWorkerRequest wr = DequeueRequest(false); if (wr == null) break; HttpRuntime.RejectRequestNow(wr, false); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ContextProperty.cs
- EntityReference.cs
- QuaternionKeyFrameCollection.cs
- PropertyBuilder.cs
- FillBehavior.cs
- DefaultBinder.cs
- QueryCacheEntry.cs
- FieldAccessException.cs
- ContextItemManager.cs
- KeyConstraint.cs
- PageRequestManager.cs
- StaticSiteMapProvider.cs
- ProvidersHelper.cs
- PeerTransportElement.cs
- IntSecurity.cs
- UInt16.cs
- validation.cs
- SafeNativeMethods.cs
- BindingMAnagerBase.cs
- SafeFileMapViewHandle.cs
- SignatureHelper.cs
- PathFigure.cs
- HandlerWithFactory.cs
- CommandBindingCollection.cs
- SafeRegistryHandle.cs
- SqlConnectionPoolGroupProviderInfo.cs
- WeakReadOnlyCollection.cs
- UserNamePasswordServiceCredential.cs
- AspProxy.cs
- MailWebEventProvider.cs
- ArraySortHelper.cs
- SqlAliaser.cs
- connectionpool.cs
- ToolStripCustomTypeDescriptor.cs
- _FtpControlStream.cs
- SafeMarshalContext.cs
- GridViewRowPresenterBase.cs
- IdnElement.cs
- WindowsImpersonationContext.cs
- ExpandSegmentCollection.cs
- SqlConnectionPoolGroupProviderInfo.cs
- BufferModeSettings.cs
- ThousandthOfEmRealDoubles.cs
- UiaCoreProviderApi.cs
- ColumnResult.cs
- SuppressMergeCheckAttribute.cs
- safesecurityhelperavalon.cs
- MemberAccessException.cs
- ConfigXmlSignificantWhitespace.cs
- BamlResourceSerializer.cs
- ReceiveMessageRecord.cs
- HtmlTitle.cs
- SchemaReference.cs
- ItemDragEvent.cs
- IIS7UserPrincipal.cs
- Int64AnimationBase.cs
- HierarchicalDataSourceControl.cs
- ReturnEventArgs.cs
- CryptoHandle.cs
- InternalsVisibleToAttribute.cs
- SettingsProviderCollection.cs
- CodeAccessSecurityEngine.cs
- _SslStream.cs
- CodeMethodInvokeExpression.cs
- DNS.cs
- XmlSchemaSimpleType.cs
- KerberosTicketHashIdentifierClause.cs
- Material.cs
- ItemCheckEvent.cs
- SymmetricAlgorithm.cs
- ClientBuildManagerCallback.cs
- Tracer.cs
- SecureEnvironment.cs
- BasicExpandProvider.cs
- Message.cs
- BaseCodePageEncoding.cs
- XmlReaderDelegator.cs
- AssemblyCollection.cs
- TemplateControlParser.cs
- RegionIterator.cs
- ExpressionsCollectionConverter.cs
- DrawingServices.cs
- HtmlEncodedRawTextWriter.cs
- AxisAngleRotation3D.cs
- ChameleonKey.cs
- DataControlFieldHeaderCell.cs
- EventRouteFactory.cs
- RSAPKCS1SignatureDeformatter.cs
- TransactionScopeDesigner.cs
- DiscardableAttribute.cs
- ConstructorBuilder.cs
- ConstructorNeedsTagAttribute.cs
- OleDbRowUpdatedEvent.cs
- COM2TypeInfoProcessor.cs
- DocumentPageView.cs
- FontCacheLogic.cs
- IdentityNotMappedException.cs
- CodeDirectionExpression.cs
- ObjectDataSourceStatusEventArgs.cs
- Item.cs