Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@ -31,6 +31,8 @@ namespace System.Web.SessionState {
using System.Web.Hosting;
using System.Web.Management;
using Microsoft.Win32;
using System.Collections.Concurrent;
using System.Collections.Generic;
public delegate void SessionStateItemExpireCallback(
string id, SessionStateStoreData item);
@ -153,7 +155,8 @@ namespace System.Web.SessionState {
private static bool s_PollIntervalRegLookedUp = false;
private static object s_PollIntervalRegLock = new object();
private static ConcurrentDictionary<string, int> s_queuedRequestsNumPerSession = new ConcurrentDictionary<string, int>();
//
// Check if we can optmize for InProc case.
// Optimization details:
@ -962,7 +965,7 @@ namespace System.Web.SessionState {
Debug.Assert(storedItem != null, "Must succeed in locking session state item.");
}
}
bool GetSessionStateItem() {
bool isCompleted = true;
bool locked;
@ -1012,6 +1015,8 @@ namespace System.Web.SessionState {
}
void PollLockedSession() {
EnsureRequestTimeout();
if (_timerCallback == null) {
_timerCallback = new TimerCallback(this.PollLockedSessionCallback);
}
@ -1019,6 +1024,9 @@ namespace System.Web.SessionState {
if (_timer == null) {
_timerId++;
// Only call this method once when setting up timer to poll the session item.
// It should not be called in timer's callback
QueueRef();
#if DBG
if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer"))
#endif
@ -1030,6 +1038,53 @@ namespace System.Web.SessionState {
}
}
private void EnsureRequestTimeout() {
// Request may be blocked in acquiring state longer than execution timeout.
// In that case, it will be timeout anyway after it gets the session item.
// So it makes sense to timeout it when waiting longer than executionTimeout.
if (_rqContext.HasTimeoutExpired) {
throw new HttpException(SR.GetString(SR.Request_timed_out));
}
}
private static bool IsRequestQueueEnabled {
get {
return (AppSettings.RequestQueueLimitPerSession != AppSettings.UnlimitedRequestsPerSession);
}
}
private void QueueRef() {
if (!IsRequestQueueEnabled || _rqId == null) {
return;
}
//
// Check the limit
int count = 0;
s_queuedRequestsNumPerSession.TryGetValue(_rqId, out count);
if (count >= AppSettings.RequestQueueLimitPerSession) {
throw new HttpException(SR.GetString(SR.Request_Queue_Limit_Per_Session_Exceeded));
}
//
// Add ref
s_queuedRequestsNumPerSession.AddOrUpdate(_rqId, 1, (key, value) => value + 1);
}
private void DequeRef() {
if (!IsRequestQueueEnabled || _rqId == null) {
return;
}
// Decrement the counter
if (s_queuedRequestsNumPerSession.AddOrUpdate(_rqId, 0, (key, value) => value - 1) == 0) {
//
// Remove the element when no more references
((ICollection<KeyValuePair<string, int>>)s_queuedRequestsNumPerSession).Remove(new KeyValuePair<string,int>(_rqId, 0));
}
}
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
private static void LookUpRegForPollInterval() {
lock (s_PollIntervalRegLock) {
@ -1167,6 +1222,8 @@ namespace System.Web.SessionState {
}
if (isCompleted || error != null) {
DequeRef();
_rqAr.Complete(false, null, error);
}
}