Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / 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
- RectangleConverter.cs
- HttpContext.cs
- SiteMapPath.cs
- Metadata.cs
- DecoderNLS.cs
- TextBox.cs
- SimpleHandlerFactory.cs
- CustomWebEventKey.cs
- ArithmeticException.cs
- ObjectSet.cs
- FirstMatchCodeGroup.cs
- AdPostCacheSubstitution.cs
- WebPartChrome.cs
- Int16.cs
- ExpressionPrefixAttribute.cs
- XPathScanner.cs
- FixedDocumentSequencePaginator.cs
- XmlComment.cs
- PropVariant.cs
- TabRenderer.cs
- WhereaboutsReader.cs
- MobileRedirect.cs
- HebrewCalendar.cs
- BulletedList.cs
- ClientCredentialsElement.cs
- LayoutSettings.cs
- WebConfigurationManager.cs
- Dictionary.cs
- CryptoKeySecurity.cs
- DbParameterHelper.cs
- WebPartZone.cs
- DependencyPropertyKind.cs
- BaseConfigurationRecord.cs
- UnauthorizedAccessException.cs
- RemoteArgument.cs
- PointIndependentAnimationStorage.cs
- Thread.cs
- xmlsaver.cs
- CaseInsensitiveHashCodeProvider.cs
- CompilerCollection.cs
- ScriptingRoleServiceSection.cs
- DirectoryObjectSecurity.cs
- DPAPIProtectedConfigurationProvider.cs
- HttpModulesSection.cs
- DoubleUtil.cs
- TypeLibConverter.cs
- DoubleLink.cs
- JsonStringDataContract.cs
- DataGridViewColumnDesignTimeVisibleAttribute.cs
- DbMetaDataCollectionNames.cs
- LogicalMethodInfo.cs
- MultiBindingExpression.cs
- XamlClipboardData.cs
- PropertyTabAttribute.cs
- Msec.cs
- MatrixTransform.cs
- CellLabel.cs
- SAPIEngineTypes.cs
- MemoryMappedFileSecurity.cs
- PropagatorResult.cs
- SapiRecoInterop.cs
- PerformanceCounterNameAttribute.cs
- WindowInteropHelper.cs
- TaskExceptionHolder.cs
- SignedPkcs7.cs
- CategoryGridEntry.cs
- TreePrinter.cs
- HuffCodec.cs
- OleDbInfoMessageEvent.cs
- DataStorage.cs
- DataSourceComponent.cs
- MailDefinition.cs
- InheritanceContextChangedEventManager.cs
- SplayTreeNode.cs
- XmlElementCollection.cs
- AliasGenerator.cs
- SessionMode.cs
- DynamicResourceExtension.cs
- ListItemParagraph.cs
- ConfigurationValue.cs
- TextElement.cs
- InputBinder.cs
- NamespaceQuery.cs
- TransformedBitmap.cs
- Effect.cs
- ThumbButtonInfoCollection.cs
- DbConnectionInternal.cs
- UpdateCompiler.cs
- HMACSHA1.cs
- HandlerBase.cs
- columnmapkeybuilder.cs
- Attributes.cs
- TailPinnedEventArgs.cs
- _FtpDataStream.cs
- smtppermission.cs
- smtppermission.cs
- ReliableMessagingHelpers.cs
- SharedMemory.cs
- ProfileGroupSettings.cs
- SecurityManager.cs