// Reset the expire time of an item based on its timeout value public override void ResetItemTimeout(HttpContext context, String id) { string key = CreateSessionStateCacheKey(id); SessionIDManager.CheckIdLength(id, true /* throwOnFail */); HttpRuntime.CacheInternal.Get(key); }
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { string key = this.CreateSessionStateCacheKey(id); CacheInternal cacheInternal = HttpRuntime.CacheInternal; int num = (int)lockId; SessionIDManager.CheckIdLength(id, true); InProcSessionState state = (InProcSessionState)cacheInternal.Get(key); if (state != null) { state._spinLock.AcquireWriterLock(); try { if (!state._locked || (state._lockCookie != num)) { return; } state._lockCookie = 0; } finally { state._spinLock.ReleaseWriterLock(); } cacheInternal.Remove(key); } }
// Unlock an item locked by GetExclusive // 'lockId' is the lock context returned by previous call to GetExclusive public override void ReleaseItemExclusive(HttpContext context, String id, object lockId) { Debug.Assert(lockId != null, "lockId != null"); string key = CreateSessionStateCacheKey(id); int lockCookie = (int)lockId; SessionIDManager.CheckIdLength(id, true /* throwOnFail */); InProcSessionState state = (InProcSessionState)HttpRuntime.CacheInternal.Get(key); /* If the state isn't there, we probably took too long to run. */ if (state == null) { return; } if (state._locked) { state._spinLock.AcquireWriterLock(); try { if (state._locked && lockCookie == state._lockCookie) { state._locked = false; } } finally { state._spinLock.ReleaseWriterLock(); } } }
public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { string key = this.CreateSessionStateCacheKey(id); SessionIDManager.CheckIdLength(id, true); InProcSessionState state = new InProcSessionState(null, null, timeout, false, DateTime.MinValue, NewLockCookie, 1); try { } finally { if (HttpRuntime.CacheInternal.UtcAdd(key, state, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, timeout, 0), CacheItemPriority.NotRemovable, this._callback) == null) { PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_TOTAL); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_ACTIVE); } } }
// Remove an item. Note that the item is originally obtained by GetExclusive // Same note as Set on lockId public override void RemoveItem(HttpContext context, String id, object lockId, SessionStateStoreData item) { Debug.Assert(lockId != null, "lockId != null"); string key = CreateSessionStateCacheKey(id); CacheInternal cacheInternal = HttpRuntime.CacheInternal; int lockCookie = (int)lockId; SessionIDManager.CheckIdLength(id, true /* throwOnFail */); InProcSessionState state = (InProcSessionState)cacheInternal.Get(key); /* If the item isn't there, we probably took too long to run. */ if (state == null) { return; } state._spinLock.AcquireWriterLock(); try { /* Only remove the item if we are the owner */ if (!state._locked || state._lockCookie != lockCookie) { return; } /* prevent overwriting when we drop the lock */ state._lockCookie = 0; } finally { state._spinLock.ReleaseWriterLock(); } cacheInternal.Remove(key); TraceSessionStats(); }
public override void CreateUninitializedItem(HttpContext context, String id, int timeout) { string key = CreateSessionStateCacheKey(id); Debug.Assert(timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES, "item.Timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES"); SessionIDManager.CheckIdLength(id, true /* throwOnFail */); Debug.Trace("SessionStateClientSet", "Inserting an uninitialized item into Cache; key = " + key); InProcSessionState state = new InProcSessionState( null, null, timeout, false, DateTime.MinValue, NewLockCookie, (int)SessionStateItemFlags.Uninitialized); // DevDivBugs 146875 // We do not want to overwrite an item with an uninitialized item if it is // already in the cache try { } finally { // protected from ThreadAbortEx object existingEntry = HttpRuntime.Cache.InternalCache.Add(key, state, new CacheInsertOptions() { SlidingExpiration = new TimeSpan(0, timeout, 0), Priority = CacheItemPriority.NotRemovable, OnRemovedCallback = _callback }); if (existingEntry == null) { PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_TOTAL); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_ACTIVE); } } }
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { string key = this.CreateSessionStateCacheKey(id); int num = (int)lockId; SessionIDManager.CheckIdLength(id, true); InProcSessionState state = (InProcSessionState)HttpRuntime.CacheInternal.Get(key); if ((state != null) && state._locked) { state._spinLock.AcquireWriterLock(); try { if (state._locked && (num == state._lockCookie)) { state._locked = false; } } finally { state._spinLock.ReleaseWriterLock(); } } }
void MakeRequest( UnsafeNativeMethods.StateProtocolVerb verb, String id, UnsafeNativeMethods.StateProtocolExclusive exclusiveAccess, int extraFlags, int timeout, int lockCookie, byte[] buf, int cb, int networkTimeout, out UnsafeNativeMethods.SessionNDMakeRequestResults results) { int hr; string uri; OutOfProcConnection conn = null; HandleRef socketHandle; bool checkVersion = false; Debug.Assert(timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES, "item.Timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES"); SessionIDManager.CheckIdLength(id, true /* throwOnFail */); if (_partitionInfo == null) { Debug.Assert(s_partitionManager != null); Debug.Assert(_partitionResolver != null); _partitionInfo = (StateServerPartitionInfo)s_partitionManager.GetPartition(_partitionResolver, id); // If its still null, we give up if (_partitionInfo == null) { throw new HttpException(SR.GetString(SR.Bad_partition_resolver_connection_string, "PartitionManager")); } } // Need to make sure we dispose the connection if anything goes wrong try { conn = (OutOfProcConnection)_partitionInfo.RetrieveResource(); if (conn != null) { socketHandle = new HandleRef(this, conn._socketHandle.Handle); } else { socketHandle = new HandleRef(this, INVALID_SOCKET); } if (_partitionInfo.StateServerVersion == -1) { // We don't need locking here because it's okay to have two // requests initializing s_stateServerVersion. checkVersion = true; } Debug.Trace("OutOfProcSessionStateStoreMakeRequest", "Calling MakeRequest, " + "socket=" + (IntPtr)socketHandle.Handle + "verb=" + verb + " id=" + id + " exclusiveAccess=" + exclusiveAccess + " timeout=" + timeout + " buf=" + ((buf != null) ? "non-null" : "null") + " cb=" + cb + " checkVersion=" + checkVersion + " extraFlags=" + extraFlags); // Have to UrlEncode id because it may contain non-URL-safe characters uri = HttpUtility.UrlEncode(s_uribase + id); hr = UnsafeNativeMethods.SessionNDMakeRequest( socketHandle, _partitionInfo.Server, _partitionInfo.Port, _partitionInfo.ServerIsIPv6NumericAddress /* forceIPv6 */, networkTimeout, verb, uri, exclusiveAccess, extraFlags, timeout, lockCookie, buf, cb, checkVersion, out results); Debug.Trace("OutOfProcSessionStateStoreMakeRequest", "MakeRequest returned: " + "hr=" + hr + " socket=" + (IntPtr)results.socket + " httpstatus=" + results.httpStatus + " timeout=" + results.timeout + " contentlength=" + results.contentLength + " uri=" + (IntPtr)results.content + " lockCookie=" + results.lockCookie + " lockDate=" + string.Format("{0:x}", results.lockDate) + " lockAge=" + results.lockAge + " stateServerMajVer=" + results.stateServerMajVer + " actionFlags=" + results.actionFlags); if (conn != null) { if (results.socket == INVALID_SOCKET) { conn.Detach(); conn = null; } else if (results.socket != socketHandle.Handle) { // The original socket is no good. We've got a new one. // Pleae note that EnsureConnected has closed the bad // one already. conn._socketHandle = new HandleRef(this, results.socket); } } else if (results.socket != INVALID_SOCKET) { conn = new OutOfProcConnection(results.socket); } if (conn != null) { _partitionInfo.StoreResource(conn); } } catch { // We just need to dispose the connection if anything bad happened if (conn != null) { conn.Dispose(); } throw; } if (hr != 0) { HttpException e = CreateConnectionException(_partitionInfo.Server, _partitionInfo.Port, hr); string phase = null; switch (results.lastPhase) { case (int)UnsafeNativeMethods.SessionNDMakeRequestPhase.Initialization: phase = SR.GetString(SR.State_Server_detailed_error_phase0); break; case (int)UnsafeNativeMethods.SessionNDMakeRequestPhase.Connecting: phase = SR.GetString(SR.State_Server_detailed_error_phase1); break; case (int)UnsafeNativeMethods.SessionNDMakeRequestPhase.SendingRequest: phase = SR.GetString(SR.State_Server_detailed_error_phase2); break; case (int)UnsafeNativeMethods.SessionNDMakeRequestPhase.ReadingResponse: phase = SR.GetString(SR.State_Server_detailed_error_phase3); break; default: Debug.Assert(false, "Unknown results.lastPhase: " + results.lastPhase); break; } WebBaseEvent.RaiseSystemEvent(SR.GetString(SR.State_Server_detailed_error, phase, "0x" + hr.ToString("X08", CultureInfo.InvariantCulture), cb.ToString(CultureInfo.InvariantCulture)), this, WebEventCodes.WebErrorOtherError, WebEventCodes.StateServerConnectionError, e); throw e; } if (results.httpStatus == 400) { if (s_usePartition) { throw new HttpException( SR.GetString(SR.Bad_state_server_request_partition_resolver, s_configPartitionResolverType, _partitionInfo.Server, _partitionInfo.Port.ToString(CultureInfo.InvariantCulture))); } else { throw new HttpException( SR.GetString(SR.Bad_state_server_request)); } } if (checkVersion) { _partitionInfo.StateServerVersion = results.stateServerMajVer; if (_partitionInfo.StateServerVersion < WHIDBEY_MAJOR_VERSION) { // We won't work with versions lower than Whidbey if (s_usePartition) { throw new HttpException( SR.GetString(SR.Need_v2_State_Server_partition_resolver, s_configPartitionResolverType, _partitionInfo.Server, _partitionInfo.Port.ToString(CultureInfo.InvariantCulture))); } else { throw new HttpException( SR.GetString(SR.Need_v2_State_Server)); } } } }
public override void SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, object lockId, bool newItem) { string key = CreateSessionStateCacheKey(id); bool doInsert = true; CacheInternal cacheInternal = HttpRuntime.CacheInternal; int lockCookieForInsert = NewLockCookie; ISessionStateItemCollection items = null; HttpStaticObjectsCollection staticObjects = null; Debug.Assert(item.Items != null, "item.Items != null"); Debug.Assert(item.StaticObjects != null, "item.StaticObjects != null"); Debug.Assert(item.Timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES, "item.Timeout <= SessionStateModule.MAX_CACHE_BASED_TIMEOUT_MINUTES"); SessionIDManager.CheckIdLength(id, true /* throwOnFail */); if (item.Items.Count > 0) { items = item.Items; } if (!item.StaticObjects.NeverAccessed) { staticObjects = item.StaticObjects; } if (!newItem) { Debug.Assert(lockId != null, "lockId != null"); InProcSessionState stateCurrent = (InProcSessionState)cacheInternal.Get(key); int lockCookie = (int)lockId; /* If the state isn't there, we probably took too long to run. */ if (stateCurrent == null) { return; } Debug.Trace("SessionStateClientSet", "state is inStorage; key = " + key); Debug.Assert((stateCurrent._flags & (int)SessionStateItemFlags.Uninitialized) == 0, "Should never set an unitialized item; key = " + key); stateCurrent._spinLock.AcquireWriterLock(); try { /* Only set the state if we are the owner */ if (!stateCurrent._locked || stateCurrent._lockCookie != lockCookie) { Debug.Trace("SessionStateClientSet", "Leave because we're not the owner; key = " + key); return; } /* We can change the state in place if the timeout hasn't changed */ if (stateCurrent._timeout == item.Timeout) { stateCurrent.Copy( items, staticObjects, item.Timeout, false, DateTime.MinValue, lockCookie, stateCurrent._flags); // Don't need to insert into the Cache because an in-place copy is good enough. doInsert = false; Debug.Trace("SessionStateClientSet", "Changing state inplace; key = " + key); } else { /* We are going to insert a new item to replace the current one in Cache * because the expiry time has changed. * * Pleas note that an insert will cause the Session_End to be incorrectly raised. * * Please note that the item itself should not expire between now and * where we do UtcInsert below because CacheInternal.Get above have just * updated its expiry time. */ stateCurrent._flags |= (int)SessionStateItemFlags.IgnoreCacheItemRemoved; /* By setting _lockCookie to 0, we prevent an overwriting by ReleaseExclusive * when we drop the lock. * The scenario can happen if another request is polling and trying to prempt * the lock we have on the item. */ lockCookieForInsert = lockCookie; stateCurrent._lockCookie = 0; } } finally { stateCurrent._spinLock.ReleaseWriterLock(); } } if (doInsert) { Debug.Trace("SessionStateClientSet", "Inserting state into Cache; key = " + key); InProcSessionState state = new InProcSessionState( items, staticObjects, item.Timeout, false, DateTime.MinValue, lockCookieForInsert, 0); try { } finally { // protected from ThreadAbortEx cacheInternal.UtcInsert( key, state, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, state._timeout, 0), CacheItemPriority.NotRemovable, _callback); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_TOTAL); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_ACTIVE); TraceSessionStats(); } } }
SessionStateStoreData DoGet(HttpContext context, String id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { string key = CreateSessionStateCacheKey(id); // Set default return values locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = 0; // Not technically necessary for InProc, but we do it to be consistent // with SQL provider SessionIDManager.CheckIdLength(id, true /* throwOnFail */); InProcSessionState state = (InProcSessionState)HttpRuntime.CacheInternal.Get(key); if (state != null) { bool lockedByOther; // True if the state is locked by another session int initialFlags; initialFlags = (int)state._flags; if ((initialFlags & (int)SessionStateItemFlags.Uninitialized) != 0) { // It is an uninitialized item. We have to remove that flag. // We only allow one request to do that. // For details, see inline doc for SessionStateItemFlags.Uninitialized flag. // If initialFlags != return value of CompareExchange, it means another request has // removed the flag. Debug.Trace("SessionStateClientSet", "Removing the Uninit flag for item; key = " + key); if (initialFlags == Interlocked.CompareExchange( ref state._flags, initialFlags & (~((int)SessionStateItemFlags.Uninitialized)), initialFlags)) { actionFlags = SessionStateActions.InitializeItem; } } if (exclusive) { lockedByOther = true; // If unlocked, use a spinlock to test and lock the state. if (!state._locked) { state._spinLock.AcquireWriterLock(); try { if (!state._locked) { lockedByOther = false; state._locked = true; state._utcLockDate = DateTime.UtcNow; state._lockCookie++; } lockId = state._lockCookie; } finally { state._spinLock.ReleaseWriterLock(); } } else { // It's already locked by another request. Return the lockCookie to caller. lockId = state._lockCookie; } } else { state._spinLock.AcquireReaderLock(); try { lockedByOther = state._locked; lockId = state._lockCookie; } finally { state._spinLock.ReleaseReaderLock(); } } if (lockedByOther) { // Item found, but locked locked = true; lockAge = DateTime.UtcNow - state._utcLockDate; return(null); } else { return(SessionStateUtility.CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout)); } } // Not found return(null); }
private void MakeRequest(System.Web.UnsafeNativeMethods.StateProtocolVerb verb, string id, System.Web.UnsafeNativeMethods.StateProtocolExclusive exclusiveAccess, int extraFlags, int timeout, int lockCookie, byte[] buf, int cb, int networkTimeout, out System.Web.UnsafeNativeMethods.SessionNDMakeRequestResults results) { int num; OutOfProcConnection o = null; bool checkVersion = false; SessionIDManager.CheckIdLength(id, true); if (this._partitionInfo == null) { this._partitionInfo = (StateServerPartitionInfo)s_partitionManager.GetPartition(this._partitionResolver, id); if (this._partitionInfo == null) { throw new HttpException(System.Web.SR.GetString("Bad_partition_resolver_connection_string", new object[] { "PartitionManager" })); } } try { HandleRef ref2; o = (OutOfProcConnection)this._partitionInfo.RetrieveResource(); if (o != null) { ref2 = new HandleRef(this, o._socketHandle.Handle); } else { ref2 = new HandleRef(this, INVALID_SOCKET); } if (this._partitionInfo.StateServerVersion == -1) { checkVersion = true; } string uri = HttpUtility.UrlEncode(s_uribase + id); num = System.Web.UnsafeNativeMethods.SessionNDMakeRequest(ref2, this._partitionInfo.Server, this._partitionInfo.Port, networkTimeout, verb, uri, exclusiveAccess, extraFlags, timeout, lockCookie, buf, cb, checkVersion, out results); if (o != null) { if (results.socket == INVALID_SOCKET) { o.Detach(); o = null; } else if (results.socket != ref2.Handle) { o._socketHandle = new HandleRef(this, results.socket); } } else if (results.socket != INVALID_SOCKET) { o = new OutOfProcConnection(results.socket); } if (o != null) { this._partitionInfo.StoreResource(o); } } catch { if (o != null) { o.Dispose(); } throw; } if (num == 0) { if (results.httpStatus == 400) { if (s_usePartition) { throw new HttpException(System.Web.SR.GetString("Bad_state_server_request_partition_resolver", new object[] { s_configPartitionResolverType, this._partitionInfo.Server, this._partitionInfo.Port.ToString(CultureInfo.InvariantCulture) })); } throw new HttpException(System.Web.SR.GetString("Bad_state_server_request")); } if (checkVersion) { this._partitionInfo.StateServerVersion = results.stateServerMajVer; if (this._partitionInfo.StateServerVersion < WHIDBEY_MAJOR_VERSION) { if (s_usePartition) { throw new HttpException(System.Web.SR.GetString("Need_v2_State_Server_partition_resolver", new object[] { s_configPartitionResolverType, this._partitionInfo.Server, this._partitionInfo.Port.ToString(CultureInfo.InvariantCulture) })); } throw new HttpException(System.Web.SR.GetString("Need_v2_State_Server")); } } } else { HttpException exception = CreateConnectionException(this._partitionInfo.Server, this._partitionInfo.Port, num); string str2 = null; switch (results.lastPhase) { case 0: str2 = System.Web.SR.GetString("State_Server_detailed_error_phase0"); break; case 1: str2 = System.Web.SR.GetString("State_Server_detailed_error_phase1"); break; case 2: str2 = System.Web.SR.GetString("State_Server_detailed_error_phase2"); break; case 3: str2 = System.Web.SR.GetString("State_Server_detailed_error_phase3"); break; } WebBaseEvent.RaiseSystemEvent(System.Web.SR.GetString("State_Server_detailed_error", new object[] { str2, "0x" + num.ToString("X08", CultureInfo.InvariantCulture), cb.ToString(CultureInfo.InvariantCulture) }), this, 0xbc1, 0xc360, exception); throw exception; } }
private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { bool flag; string key = this.CreateSessionStateCacheKey(id); locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = SessionStateActions.None; SessionIDManager.CheckIdLength(id, true); InProcSessionState state = (InProcSessionState)HttpRuntime.CacheInternal.Get(key); if (state == null) { return(null); } int comparand = state._flags; if (((comparand & 1) != 0) && (comparand == Interlocked.CompareExchange(ref state._flags, comparand & -2, comparand))) { actionFlags = SessionStateActions.InitializeItem; } if (exclusive) { flag = true; if (!state._locked) { state._spinLock.AcquireWriterLock(); try { if (!state._locked) { flag = false; state._locked = true; state._utcLockDate = DateTime.UtcNow; state._lockCookie++; } lockId = state._lockCookie; goto Label_00FE; } finally { state._spinLock.ReleaseWriterLock(); } } lockId = state._lockCookie; } else { state._spinLock.AcquireReaderLock(); try { flag = state._locked; lockId = state._lockCookie; } finally { state._spinLock.ReleaseReaderLock(); } } Label_00FE: if (flag) { locked = true; lockAge = (TimeSpan)(DateTime.UtcNow - state._utcLockDate); return(null); } return(SessionStateUtility.CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout)); }
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { string key = this.CreateSessionStateCacheKey(id); bool flag = true; CacheInternal cacheInternal = HttpRuntime.CacheInternal; int newLockCookie = NewLockCookie; ISessionStateItemCollection sessionItems = null; HttpStaticObjectsCollection staticObjects = null; SessionIDManager.CheckIdLength(id, true); if (item.Items.Count > 0) { sessionItems = item.Items; } if (!item.StaticObjects.NeverAccessed) { staticObjects = item.StaticObjects; } if (!newItem) { InProcSessionState state = (InProcSessionState)cacheInternal.Get(key); int lockCookie = (int)lockId; if (state == null) { return; } state._spinLock.AcquireWriterLock(); try { if (!state._locked || (state._lockCookie != lockCookie)) { return; } if (state._timeout == item.Timeout) { state.Copy(sessionItems, staticObjects, item.Timeout, false, DateTime.MinValue, lockCookie, state._flags); flag = false; } else { state._flags |= 2; newLockCookie = lockCookie; state._lockCookie = 0; } } finally { state._spinLock.ReleaseWriterLock(); } } if (flag) { InProcSessionState state2 = new InProcSessionState(sessionItems, staticObjects, item.Timeout, false, DateTime.MinValue, newLockCookie, 0); try { } finally { cacheInternal.UtcInsert(key, state2, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, state2._timeout, 0), CacheItemPriority.NotRemovable, this._callback); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_TOTAL); PerfCounters.IncrementCounter(AppPerfCounter.SESSIONS_ACTIVE); } } }