/// <summary> /// Обобщенный вспомогательный метод для получения доступа к сессии в базе данных. /// Используется как GetItem, так и GetItemExclusive. /// </summary> private SessionStateStoreData GetSessionItem(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { locked = false; lockAge = new TimeSpan(); lockId = null; actions = 0; var sessionItem = TraceSessionStorage.GetSessionItem(id); // Сессия не найдена if (sessionItem == null) { return(null); } // Сессия найдена, но заблокирована if (sessionItem.Locked) { locked = true; lockAge = DateTime.UtcNow - sessionItem.LockDate; lockId = sessionItem.LockId; return(null); } // Сессия найдена, требуется эксклюзинвый доступ. if (exclusive) { lock (sessionItem.SyncRoot) { sessionItem.LockId += 1; sessionItem.Locked = true; sessionItem.LockDate = DateTime.UtcNow; sessionItem.DateLastChanged = DateTime.Now; TraceSessionStorage.MarkSessionUpdated(sessionItem); } } locked = exclusive; lockAge = DateTime.UtcNow - sessionItem.LockDate; lockId = sessionItem.LockId; var data = (sessionItem.ItemContent == null) ? CreateNewStoreData(context, _timeoutSession) : Deserialize(context, sessionItem.ItemContent, _timeoutSession); data.Items["UserId"] = sessionItem.IdUser; return(data); }
/// <summary> /// Удаляет запись о состоянии сессии. /// </summary> public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { var sessionItem = TraceSessionStorage.GetSessionItem(id); lock (sessionItem.SyncRoot) { if (sessionItem.LockId != (int)lockId) { return; } sessionItem.DateLastChanged = DateTime.Now; TraceSessionStorage.RemoveSession(sessionItem); } }
/// <summary> /// Сохраняем состояние сессии и снимаем блокировку. /// </summary> public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { context.Items[InternalStoreInfo.KEY] = null; var intLockId = lockId == null ? 0 : (int)lockId; var userId = (int)item.Items["UserId"]; var data = ((SessionStateItemCollection)item.Items); data.Remove("UserId"); // Сериализуем переменные var itemContent = Serialize(data); // Если это новая сессия, которой еще нет в базе данных. if (newItem) { CreateUninitializedItem(context, id, _timeoutSession); //return;//Не выходим из функции, т.к. в новую сессию еще надо записать данные. } // Если это старая сессия, проверяем совпадает ли ключ блокировки, // а после сохраняем состояние и снимаем блокировку. var sessionItem = TraceSessionStorage.GetSessionItem(id); if (sessionItem != null) { lock (sessionItem.SyncRoot) { if (lockId == null || sessionItem.LockId == (int)lockId) { sessionItem.IdUser = userId; sessionItem.ItemContent = itemContent; sessionItem.Expires = DateTime.UtcNow.AddMinutes(_timeoutSession); sessionItem.Locked = false; sessionItem.DateLastChanged = DateTime.Now; if (!newItem || (newItem && itemContent != null)) { TraceSessionStorage.MarkSessionUpdated(sessionItem); } } } } }
/// <summary> /// Удаляем блокировку сессии, освобождаем ее для других потоков. /// </summary> public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { var sessionItem = TraceSessionStorage.GetSessionItem(id); if (sessionItem.LockId != (int)lockId) { return; } lock (sessionItem.SyncRoot) { sessionItem.Locked = false; sessionItem.Expires = DateTime.UtcNow.AddMinutes(_timeoutSession); sessionItem.DateLastChanged = DateTime.Now; TraceSessionStorage.MarkSessionUpdated(sessionItem); } }
/// <summary> /// Сбрасывает счетчик жизни сессии. /// </summary> public override void ResetItemTimeout(HttpContext context, string id) { var sessionItem = TraceSessionStorage.GetSessionItem(id); if (sessionItem == null) { return; } lock (sessionItem.SyncRoot) { // Обновляем время жизни только если есть данные в сессии. Пустым сессиям положено умирать. if (sessionItem.ItemContent != null) { sessionItem.Expires = DateTime.UtcNow.AddMinutes(_timeoutSession); sessionItem.DateLastChanged = DateTime.Now; TraceSessionStorage.MarkSessionUpdated(sessionItem); } } }