/// <summary> /// Called when SessionState = ReadOnly /// </summary> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { RedisConnection redisConnection = ConnectionUtils.Connect("10.0.0.3:6379"); { redisConnection.Open(); var result = redisConnection.Strings.Get(0, id); byte[] raw = redisConnection.Wait(result); actions = SessionStateActions.None; SessionEntity sessionEntity = GetFromBytes(raw); if (sessionEntity == null || sessionEntity.SessionItems == null ) { locked = false; lockId = _lock; lockAge = TimeSpan.MinValue; return null; } ISessionStateItemCollection sessionItems = new SessionStateItemCollection(); foreach (string key in sessionEntity.SessionItems.Keys) { sessionItems[key] = sessionEntity.SessionItems[key]; } SessionStateStoreData data = new SessionStateStoreData(sessionItems, _staticObjects, context.Session.Timeout); locked = false; lockId = _lock; lockAge = TimeSpan.MinValue; return data; } }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var redis = GetRedisConnection(); var getSessionData = redis.Hashes.GetAll(0, GetKeyForSessionId(id)); locked = false; lockAge = new TimeSpan(0); lockId = null; actions = SessionStateActions.None; if (getSessionData.Result == null) { return null; } else { var sessionItems = new SessionStateItemCollection(); var sessionDataHash = getSessionData.Result; if (sessionDataHash.Count == 3) { sessionItems = Deserialize(sessionDataHash["data"]); var timeoutMinutes = BitConverter.ToInt32(sessionDataHash["timeoutMinutes"], 0); redis.Keys.Expire(0, GetKeyForSessionId(id), timeoutMinutes * 60); } return new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), redisConfig.SessionTimeout); } }
SessionStateStoreData GetItemInternal (HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { Trace.WriteLine ("SessionStateServerHandler.GetItemInternal"); Trace.WriteLine ("\tid == " + id); Trace.WriteLine ("\tpath == " + context.Request.FilePath); locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; if (id == null) return null; StateServerItem item = stateServer.GetItem (id, out locked, out lockAge, out lockId, out actions, exclusive); if (item == null) { Trace.WriteLine ("\titem is null (locked == " + locked + ", actions == " + actions + ")"); return null; } if (actions == SessionStateActions.InitializeItem) { Trace.WriteLine ("\titem needs initialization"); return CreateNewStoreData (context, item.Timeout); } SessionStateItemCollection items = null; HttpStaticObjectsCollection sobjs = null; MemoryStream stream = null; BinaryReader reader = null; try { if (item.CollectionData != null && item.CollectionData.Length > 0) { stream = new MemoryStream (item.CollectionData); reader = new BinaryReader (stream); items = SessionStateItemCollection.Deserialize (reader); } else items = new SessionStateItemCollection (); if (item.StaticObjectsData != null && item.StaticObjectsData.Length > 0) sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData); else sobjs = new HttpStaticObjectsCollection (); } catch (Exception ex) { throw new HttpException ("Failed to retrieve session state.", ex); } finally { if (reader != null) reader.Close (); } return new SessionStateStoreData (items, sobjs, item.Timeout); }
internal StateServerItem GetItem (string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { Console.WriteLine ("RemoteStateServer.GetItem"); Console.WriteLine ("\tid == {0}", id); locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; LockableStateServerItem item = Retrieve (id); if (item == null || item.item.IsAbandoned ()) { Console.WriteLine ("\tNo item for that id (abandoned == {0})", item != null ? item.item.IsAbandoned() : false); return null; } try { Console.WriteLine ("\tacquiring reader lock"); item.rwlock.AcquireReaderLock (lockAcquireTimeout); if (item.item.Locked) { Console.WriteLine ("\titem is locked"); locked = true; lockAge = DateTime.UtcNow.Subtract (item.item.LockedTime); lockId = item.item.LockId; return null; } Console.WriteLine ("\teleasing reader lock"); item.rwlock.ReleaseReaderLock (); if (exclusive) { Console.WriteLine ("\tacquiring writer lock"); item.rwlock.AcquireWriterLock (lockAcquireTimeout); Console.WriteLine ("\tlocking the item"); item.item.Locked = true; item.item.LockedTime = DateTime.UtcNow; item.item.LockId++; Console.WriteLine ("\tnew lock id == {0}", item.item.LockId); lockId = item.item.LockId; } } catch { throw; } finally { if (item.rwlock.IsReaderLockHeld) { Console.WriteLine ("\treleasing reader lock [finally]"); item.rwlock.ReleaseReaderLock (); } if (item.rwlock.IsWriterLockHeld) { Console.WriteLine ("\treleasing writer lock [finally]"); item.rwlock.ReleaseWriterLock (); } } Console.WriteLine ("\treturning an item"); actions = item.item.Action; return item.item; }
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var e = Get(context, true, id, out locked, out lockAge, out lockId, out actions); return (e == null) ? null : e.ToStoreData(context); }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actionFlags); }
/// <summary> /// Retrieves the session data from the data source. If the lockRecord parameter is true /// (in the case of GetItemExclusive), then the record is locked and we return a new lockId /// and lockAge. /// </summary> /// <param name="bucket">Reference to the couchbase bucket we are using</param> /// <param name="context">HttpContext for the current request</param> /// <param name="acquireLock">True to aquire the lock, false to not aquire it</param> /// <param name="id">Session ID for the session</param> /// <param name="locked">Returns true if the session item is locked, otherwise false</param> /// <param name="lockAge">Returns the amount of time that the item has been locked</param> /// <param name="lockId">Returns lock identifier for the current request</param> /// <param name="actions">Indicates whether the current sessions is an uninitialized, cookieless session</param> /// <returns>SessionStateItem object containing the session state data</returns> public static SessionStateItem GetSessionStoreItem( IBucket bucket, HttpContext context, bool acquireLock, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = SessionStateActions.None; var e = SessionStateItem.Load(bucket, id, false); if (e == null) return null; if (acquireLock) { // repeat until we can update the retrieved // item (i.e. nobody changes it between the // time we get it from the store and updates it s attributes) // Save() will return false if Cas() fails while (true) { if (e.LockId > 0) break; actions = e.Flag; e.LockId = _exclusiveAccess ? e.HeadCas : 0; e.LockTime = DateTime.UtcNow; e.Flag = SessionStateActions.None; // try to update the item in the store if (e.SaveHeader(bucket, id, _exclusiveAccess)) { locked = true; lockId = e.LockId; return e; } // it has been modified between we loaded and tried to save it e = SessionStateItem.Load(bucket, id, false); if (e == null) return null; } } locked = true; lockAge = DateTime.UtcNow - e.LockTime; lockId = e.LockId; actions = SessionStateActions.None; return acquireLock ? null : e; }
private SessionStateStoreData GetItem(bool exclusive, System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { actions = 0; locked = false; lockId = 0; lockAge = TimeSpan.Zero; var collection = this._mongo.GetCollection(); if (exclusive && !this._mongo.LockSession(collection, id)) { var previouslyLockedSession = this._mongo.GetMongoSessionObject(collection, id); if (previouslyLockedSession == null) { lockId = previouslyLockedSession.LockID; lockAge = DateTime.UtcNow - previouslyLockedSession.LockedDate; } this.LogEvent(id, context.Request.RawUrl, GetUsername(context.User), "Unable to obtain lock - " + lockAge); return null; } var sessionObject = this._mongo.GetMongoSessionObject(collection, id); if (sessionObject == null) { this.LogEvent(id, context.Request.RawUrl, GetUsername(context.User), "No session"); return null; } if (sessionObject.ExpiresDate < DateTime.UtcNow) { this._mongo.ClearMongoSessionObject(collection, id); this.LogEvent(id, context.Request.RawUrl, GetUsername(context.User), "Session has expired"); return null; } locked = sessionObject.IsLocked; if (locked) { lockAge = DateTime.UtcNow - sessionObject.LockedDate; lockId = sessionObject.LockID; this.LogEvent(id, context.Request.RawUrl, GetUsername(context.User), "Obtained lock on session - " + lockId); } actions = (SessionStateActions)sessionObject.Flags; sessionObject.Flags = 0; collection.Save(sessionObject); if (actions == SessionStateActions.InitializeItem) { return CreateNewStoreData(context, (int)this._timeoutInMinutes); } return Deserialize(context, sessionObject.SessionData, sessionObject.Timeout); }
public override SessionStateStoreData GetItemExclusive( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return this.GetSessionItem(true, context, id, out locked, out lockAge, out lockId, out actions); }
public StateServerItem (byte [] collection_data, byte [] sobjs_data, int timeout) { this.CollectionData = collection_data; this.StaticObjectsData = sobjs_data; this.Timeout = timeout; this.last_access = DateTime.UtcNow; this.Locked = false; this.LockId = Int32.MinValue; this.LockedTime = DateTime.MinValue; this.Action = SessionStateActions.None; }
public Session(string id, string applicationName, int timeout, Binary sessionItems, int sessionItemsCount,SessionStateActions actionFlags ) { this._sessionID = id; this._applicationName = applicationName; this._lockDate = DateTime.Now; this._lockID = 0; this._timeout = timeout; this._locked = false; this._sessionItems = sessionItems; this._sessionItemsCount = sessionItemsCount; this._flags = (int)actionFlags; this._created = DateTime.Now; this._expires = DateTime.Now.AddMinutes((Double)this._timeout); }
/// <summary> /// Returns read-only session-state data from the session data store. /// </summary> /// <param name="context">The <see cref="T:System.Web.HttpContext" /> for the current request.</param> /// <param name="id">The <see cref="P:System.Web.SessionState.HttpSessionState.SessionID" /> for the current /// request.</param> /// <param name="locked">When this method returns, contains a Boolean value that is set to true if a lock /// is successfully obtained; otherwise, false.</param> /// <param name="lockAge">When this method returns, contains a <see cref="T:System.TimeSpan" /> object that /// is set to the amount of time that an item in the session data store has been locked.</param> /// <param name="lockId">When this method returns, contains an object that is set to the lock identifier /// for the current request. For details on the lock identifier, see "Locking Session-Store Data" in /// the <see cref="T:System.Web.SessionState.SessionStateStoreProviderBase" /> class summary.</param> /// <param name="actions">When this method returns, contains one of the /// <see cref="T:System.Web.SessionState.SessionStateActions" /> values, indicating whether the current /// session is an uninitialized, cookieless session.</param> /// <returns> /// A <see cref="T:System.Web.SessionState.SessionStateStoreData" /> populated with session values /// and information from the session data store. /// </returns> public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { actions = SessionStateActions.None; // Our items never need initialization. lockAge = TimeSpan.Zero; lockId = null; var lockId0 = Interlocked.Increment(ref _lockId); var key = GetKey(id); var lockResult = LockItem(key, lockId0); // No item found. if (lockResult == null) { locked = false; return(null); } // Item was already locked. if (!lockResult.Success) { locked = true; Debug.Assert(lockResult.LockTime != null); lockAge = DateTime.UtcNow - lockResult.LockTime.Value; lockId = lockResult.LockId; return(null); } // Item found and lock obtained. locked = false; lockId = lockId0; if (lockId0 != lockResult.Data.LockId) { throw new IgniteException(string.Format(CultureInfo.InvariantCulture, "Invalid session state lock result, " + "expected lockId: {0}, actual: {1}", lockId0, lockResult.Data.LockId)); } return(lockResult.Data); }
public Session(string id, string applicationName, int timeout, BsonBinaryData sessionItems, int sessionItemsCount, SessionStateActions actionFlags) { DateTime now = DateTime.Now; SessionID = id; ApplicationName = applicationName; LockDate = now; LockID = 0; Timeout = timeout; Locked = false; SessionItems = sessionItems; SessionItemsCount = sessionItemsCount; Flags = (int)actionFlags; Created = now; Expires = now.AddMinutes((Double)this.Timeout); }
/// <summary> /// Returns read-only session-state data from the session data store. /// </summary> /// <param name="context">The current request context</param> /// <param name="id">The session id</param> /// <param name="locked">Indicates if the item is locked in the data store (always false)</param> /// <param name="lockAge">Indicates the age of the lock (always TimeSpan.MaxValue)</param> /// <param name="lockId">An object that represents the lock ID</param> /// <param name="actions">Actions to perform after the request (always SessionStateActions.None)</param> /// <returns></returns> public override SessionStateStoreData GetItemExclusive( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return(GetItem( context, id, out locked, out lockAge, out lockId, out actions)); }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { // set default out parameters locked = false; lockAge = new TimeSpan(); lockId = null; actions = SessionStateActions.None; // try to get the session from cache. string sessionString = cache.GetAsync<string>(id).Result; if (string.IsNullOrEmpty(sessionString)) return null; var sessionItems = JsonConvert.DeserializeObject<SessionStateItemCollection>(sessionString); var data = new SessionStateStoreData(sessionItems, null, 60); // todo: set timeout. return data; }
internal StateServerItem GetItem (string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; LockableStateServerItem item = Retrieve (id); if (item == null || item.item.IsAbandoned ()) return null; try { item.rwlock.AcquireReaderLock (lockAcquireTimeout); if (item.item.Locked) { locked = true; lockAge = DateTime.UtcNow.Subtract (item.item.LockedTime); lockId = item.item.LockId; return null; } item.rwlock.ReleaseReaderLock (); if (exclusive) { item.rwlock.AcquireWriterLock (lockAcquireTimeout); item.item.Locked = true; item.item.LockedTime = DateTime.UtcNow; item.item.LockId++; lockId = item.item.LockId; } } catch { throw; } finally { if (item.rwlock.IsReaderLockHeld) item.rwlock.ReleaseReaderLock (); if (item.rwlock.IsWriterLockHeld) item.rwlock.ReleaseWriterLock (); } actions = item.item.Action; return item.item; }
public override SessionStateStoreData GetItem (HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { locked = false; lockAge = TimeSpan.Zero; lockId = null; actions = SessionStateActions.None; if (id == null) return null; HttpSession session = GetSession (context, false, false); if (session == null) return null; ServletSessionStateItemCollection sessionState = session.getAttribute (J2EEConsts.SESSION_STATE) as ServletSessionStateItemCollection; if (sessionState == null) //was not set sessionState = new ServletSessionStateItemCollection (context); return new SessionStateStoreData ( sessionState, sessionState.StaticObjects, GetIntervalInMinutes(session.getMaxInactiveInterval ())); }
private void ResetPerRequestFields() { _rqSessionState = null; _rqId = null; _rqSessionItems = null; _rqStaticObjects = null; _rqIsNewSession = false; _rqSessionStateNotFound = true; _rqRequiresState = false; _rqReadonly = false; _rqItem = null; _rqContext = null; _rqLockId = null; _rqExecutionTimeout = TimeSpan.Zero; _rqAddedCookie = false; _rqIdNew = false; _rqActionFlags = 0; _rqSupportSessionIdReissue = false; }
/// <summary> /// Returns read-only session-state data from the session data store. /// </summary> /// <param name="context">The current request context</param> /// <param name="id">The session id</param> /// <param name="locked">Indicates if the item is locked in the data store (always false)</param> /// <param name="lockAge">Indicates the age of the lock (always TimeSpan.MaxValue)</param> /// <param name="lockId">An object that represents the lock ID</param> /// <param name="actions">Actions to perform after the request (always SessionStateActions.None)</param> /// <returns></returns> public override SessionStateStoreData GetItem( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var ids = SharedSessionIDManager.GetSessionIdAndServer(id); var timestamp = SharedSessionIDManager.GetSessionTimestamp(id); var data = SharedSessionServerManager.GetData(ids[1], ids[0], timestamp); locked = false; lockAge = TimeSpan.MaxValue; lockId = new Object(); actions = SessionStateActions.None; return(Deserialize(context, data.Data, data.TimeOut)); }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var newContext = WrapContext(context); try { SessionInitializationActions newActions; var data = _store.GetItem(newContext, id, out locked, out lockAge, out lockId, out newActions); actions = ToSessionStateActions(newActions); return((SessionStateStoreData)data); } finally { newContext.Finalize(); } }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var redis = GetRedisConnection(); var getSessionData = redis.Hashes.GetAll(0, GetKeyForSessionId(id)); locked = false; lockAge = new TimeSpan(0); lockId = null; actions = SessionStateActions.None; if (getSessionData.Result == null) { return(null); } else { var sessionItems = new SessionStateItemCollection(); var sessionDataHash = getSessionData.Result; if (sessionDataHash.Count == 3) { var ms = new MemoryStream(sessionDataHash["data"]); if (ms.Length > 0) { var reader = new BinaryReader(ms); sessionItems = SessionStateItemCollection.Deserialize(reader); } var timeoutMinutes = BitConverter.ToInt32(sessionDataHash["timeoutMinutes"], 0); redis.Keys.Expire(0, GetKeyForSessionId(id), timeoutMinutes * 60); } return(new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), redisConfig.SessionTimeout)); } }
/// <summary> /// This method performs the same work as the GetItemExclusive method, except that it does not attempt to lock the session item in the data store. /// </summary> /// <param name="context">The HttpContext instance for the current request</param> /// <param name="id">The session identifier.</param> /// <param name="locked">An output parameter indicating whether the item is currently exclusively locked.</param> /// <param name="lockAge">The age of the exclusive lock (if present)</param> /// <param name="lockId">The identifier of the exclusive lock (if present)</param> /// <param name="actions">Used with sessions whose Cookieless property is true, /// when the regenerateExpiredSessionId attribute is set to true. /// An actionFlags value set to InitializeItem (1) indicates that the entry in the session data store is a /// new session that requires initialization.</param> /// <returns>The session data</returns> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { try { Logger.Debug("Beginning GetItem. SessionId={0}.", id); var item = GetSessionStoreItem(false, context, id, 0, out locked, out lockAge, out lockId, out actions); Logger.Debug("Completed GetItem. SessionId={0}, locked={1}, lockAge={2}, lockId={3}, actions={4}.", id, locked, lockAge, lockId, actions); return(item); } catch (Exception ex) { Logger.ErrorException(string.Format("Error during GetItem. SessionId={0}.", id), ex); throw; } }
SessionStateStoreData DoGet(HttpContext context, String id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = SessionStateActions.None; SessionState state = SessionState.FromJson(_cache.Get <string>(id)); if (state == null) { return(null); } //_cache.Set(id, state, state._timeout); return(CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout)); }
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { // set default out parameters locked = false; lockAge = new TimeSpan(); lockId = null; actions = SessionStateActions.None; // try to get the session from cache. string sessionString = cache.GetAsync <string>(id).Result; if (string.IsNullOrEmpty(sessionString)) { return(null); } var sessionItems = JsonConvert.DeserializeObject <SessionStateItemCollection>(sessionString); var data = new SessionStateStoreData(sessionItems, null, 60); // todo: set timeout. return(data); }
public void GetItemReturnsExpectedSessionStateStoreDataWhenItemHasNotExpired() { // Arrange string expectedAppName = "You are everything ... to me"; string appPath = "Application path"; var subject = TestStoreProviderFactory.SetupStoreProvider(appPath, MockHostingProvider); NameValueCollection keyPairs = new NameValueCollection(); keyPairs.Set("applicationName", expectedAppName); bool locked = false; TimeSpan lockAge = new TimeSpan(); SessionStateActions actions = new SessionStateActions(); object lockId = null; string providedSessionId = "A sessionId"; SessionStateDocument sessionObject = TestSessionDocumentFactory.CreateSessionStateDocument(providedSessionId, expectedAppName); sessionObject.Expiry = DateTime.UtcNow.AddDays(1); var sessionItems = new SessionStateItemCollection(); sessionItems["ACar"] = new Car("A6", "Audi"); sessionObject.SessionItems = subject.Serialize(sessionItems); MockDocumentSession.Setup(cmd => cmd.Load<SessionStateDocument>(SessionStateDocument.GenerateDocumentId(providedSessionId, expectedAppName))).Returns(sessionObject); subject.Initialize("A name", keyPairs, MockDocumentStore.Object); // Act var result = subject.GetItem(new HttpContext(new SimpleWorkerRequest("", "", "", "", new StringWriter())), "A sessionId", out locked, out lockAge, out lockId , out actions ); // Assert Assert.IsNotNull(result); Assert.AreEqual(1, result.Items.Count); Assert.IsInstanceOf<Car>(result.Items[0]); Assert.AreEqual("A6", ((Car)result.Items[0]).Name); Assert.AreEqual("Audi", ((Car)result.Items[0]).Manufacturer); }
private void ResetPerRequestFields() { this._rqSessionState = null; this._rqId = null; this._rqSessionItems = null; this._rqStaticObjects = null; this._rqIsNewSession = false; this._rqSessionStateNotFound = true; this._rqReadonly = false; this._rqItem = null; this._rqContext = null; this._rqAr = null; this._rqLockId = null; this._rqInCallback = 0; this._rqLastPollCompleted = DateTime.MinValue; this._rqExecutionTimeout = TimeSpan.Zero; this._rqAddedCookie = false; this._rqIdNew = false; this._rqActionFlags = SessionStateActions.None; this._rqIctx = null; this._rqChangeImpersonationRefCount = 0; this._rqTimerThreadImpersonationIctx = null; this._rqSupportSessionIdReissue = false; }
private SessionStateStoreData GetItem(bool isExclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { locked = false; lockAge = TimeSpan.Zero; lockId = null; actions = SessionStateActions.None; SessionStateStoreData result = null; var key = GetSessionIdKey(id); using (var client = GetClient()) using (var distributedLock = GetDistributedLock(client, key)) { if (distributedLock.LockState == DistributedLock.LOCK_NOT_ACQUIRED) { options.OnDistributedLockNotAcquired(id); return(null); } var stateRaw = client.GetAllEntriesFromHashRaw(key); RedisSessionState state; if (!RedisSessionState.TryParse(stateRaw, out state)) { return(null); } actions = state.Flags; if (state.Locked) { locked = true; lockId = state.LockId; lockAge = DateTime.UtcNow - state.LockDate; return(null); } if (isExclusive) { locked = state.Locked = true; state.LockDate = DateTime.UtcNow; lockAge = TimeSpan.Zero; lockId = ++state.LockId; } state.Flags = SessionStateActions.None; UseTransaction(client, transaction => { transaction.QueueCommand(c => c.SetRangeInHashRaw(key, state.ToMap())); transaction.QueueCommand(c => c.ExpireEntryIn(key, TimeSpan.FromMinutes(state.Timeout))); }); var items = actions == SessionStateActions.InitializeItem ? new SessionStateItemCollection() : state.Items; result = new SessionStateStoreData(items, staticObjectsGetter(context), state.Timeout); } return(result); }
/// <summary> /// Get the session for DynamoDB and optionally lock the record. /// </summary> /// <param name="lockRecord"></param> /// <param name="context"></param> /// <param name="sessionId"></param> /// <param name="locked"></param> /// <param name="lockAge"></param> /// <param name="lockId"></param> /// <param name="actionFlags"></param> /// <returns></returns> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string sessionId, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = Guid.NewGuid().ToString(); locked = false; actionFlags = SessionStateActions.None; bool foundRecord = false; bool deleteData = false; DateTime newLockedDate = DateTime.Now; Document session = null; if (lockRecord) { Document lockDoc = new Document(); lockDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); lockDoc[ATTRIBUTE_LOCK_ID] = lockId.ToString(); lockDoc[ATTRIBUTE_LOCKED] = true; lockDoc[ATTRIBUTE_LOCK_DATE] = DateTime.Now; try { session = this._table.UpdateItem(lockDoc, LOCK_UPDATE_CONFIG); locked = false; } catch (ConditionalCheckFailedException) { // This means the record is already locked by another request. locked = true; } } if (session == null) { session = this._table.GetItem(GetHashKey(sessionId), CONSISTENT_READ_GET); if (session == null && lockRecord) { locked = true; } } string serializedItems = null; if (session != null) { DateTime expire = (DateTime)session[ATTRIBUTE_EXPIRES]; if (expire < DateTime.Now) { deleteData = true; locked = false; } else { foundRecord = true; DynamoDBEntry entry; if (session.TryGetValue(ATTRIBUTE_SESSION_ITEMS, out entry)) { serializedItems = (string)entry; } if (session.Contains(ATTRIBUTE_LOCK_ID)) { lockId = (string)session[ATTRIBUTE_LOCK_ID]; } if (session.Contains(ATTRIBUTE_FLAGS)) { actionFlags = (SessionStateActions)((int)session[ATTRIBUTE_FLAGS]); } if (session[ATTRIBUTE_LOCK_DATE] != null) { DateTime lockDate = (DateTime)session[ATTRIBUTE_LOCK_DATE]; lockAge = DateTime.Now.Subtract(lockDate); } } } if (deleteData) { this.deleteItem(sessionId); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; lockId = null; } // If the record was found and you obtained a lock, then clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { if (actionFlags == SessionStateActions.InitializeItem) { Document updateDoc = new Document(); updateDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); updateDoc[ATTRIBUTE_FLAGS] = 0; this._table.UpdateItem(updateDoc); item = CreateNewStoreData(context, (int)this._timeout.TotalMinutes); } else { item = deserialize(context, serializedItems, (int)this._timeout.TotalMinutes); } } return(item); }
/// <summary> /// Returns session-state data from the DynamoDB table. /// </summary> /// <param name="context"></param> /// <param name="sessionId"></param> /// <param name="locked"></param> /// <param name="lockAge"></param> /// <param name="lockId"></param> /// <param name="actionFlags"></param> /// <returns></returns> public override SessionStateStoreData GetItemExclusive(HttpContext context, string sessionId, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { LogInfo("GetItemExclusive", sessionId, context); return GetSessionStoreItem(true, context, sessionId, out locked, out lockAge, out lockId, out actionFlags); }
private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = SessionStateActions.None; RedisSessionState state = RedisSessionState.FromJson(RedisBase.Item_Get<string>(id)); if (state == null) { return null; } RedisBase.Item_SetExpire(id, state._timeout); return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout); }
// we don't use the retry policy itself in this function because out parameters are not well handled by // retry policies private SessionStateStoreData GetSession( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { Debug.Assert(context != null, "The Http context is null"); SecUtility.CheckParameter(ref id, true, true, false, ProvidersConfiguration.MaxStringPropertySizeInChars, "id"); SessionRow session = null; int curRetry = 0; bool retry = false; // Assign default values to out parameters locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = SessionStateActions.None; do { retry = false; try { TableServiceContext svc = this.CreateDataServiceContext(); session = GetSession(id, svc); // Assign default values to out parameters locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = SessionStateActions.None; // if the blob does not exist, we return null // ASP.NET will call the corresponding method for creating the session if (session == null) { return null; } if (session.Initialized == false) { Debug.Assert(session.Locked == false, "The session is locked"); actions = SessionStateActions.InitializeItem; session.Initialized = true; } session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout); if (exclusive) { if (!session.Locked) { if (session.Lock == int.MaxValue) { session.Lock = 0; } else { session.Lock++; } session.LockDateUtc = DateTime.UtcNow; } lockId = session.Lock; locked = session.Locked; session.Locked = true; } lockAge = DateTime.UtcNow.Subtract(session.LockDateUtc); lockId = session.Lock; if (locked == true) { return null; } // let's try to write this back to the data store // in between, someone else could have written something to the store for the same session // we retry a number of times; if all fails, we throw an exception svc.UpdateObject(session); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { // precondition fails indicates problems with the status code if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.PreconditionFailed) { retry = true; } else { throw new ProviderException("Error accessing the data store.", e); } } } while (retry && curRetry++ < NumRetries); // ok, now we have successfully written back our state // we can now read the blob // note that we do not need to care about read/write locking when accessing the // blob because each time we write a new session we create a new blob with a different name SessionStateStoreData result = null; MemoryStream stream = null; StreamReader reader = null; try { try { BlobProperties properties; stream = this.blobProvider.GetBlobContent(session.BlobName, out properties); } catch (Exception e) { throw new ProviderException("Couldn't read session blob!", e); } reader = new StreamReader(stream); if (actions == SessionStateActions.InitializeItem) { // Return an empty SessionStateStoreData result = new SessionStateStoreData( new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), session.Timeout); } else { // Read Items, StaticObjects, and Timeout from the file byte[] items = Convert.FromBase64String(reader.ReadLine()); byte[] statics = Convert.FromBase64String(reader.ReadLine()); int timeout = session.Timeout; // Deserialize the session result = DeserializeSession(items, statics, timeout); } } finally { if (stream != null) { stream.Close(); } if (reader != null) { reader.Close(); } } return result; }
private SessionStateStoreData GetSessionStateStoreData(bool exclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { actions = SessionStateActions.None; lockAge = TimeSpan.Zero; locked = false; lockId = null; var query = Query.And(Query.EQ("applicationVirtualPath", HostingEnvironment.ApplicationVirtualPath), Query.EQ("id", id)); var bsonDocument = this.mongoCollection.FindOneAs <BsonDocument>(query); if (bsonDocument == null) { locked = false; } else if (bsonDocument["expires"].ToUniversalTime() <= DateTime.Now) { locked = false; this.mongoCollection.Remove(Query.And(Query.EQ("applicationVirtualPath", HostingEnvironment.ApplicationVirtualPath), Query.EQ("id", id))); } else if (bsonDocument["locked"].AsBoolean == true) { lockAge = DateTime.Now.Subtract(bsonDocument["lockDate"].ToUniversalTime()); locked = true; lockId = bsonDocument["lockId"].AsInt32; } else { locked = false; lockId = bsonDocument["lockId"].AsInt32; actions = (SessionStateActions)bsonDocument["sessionStateActions"].AsInt32; } if (exclusive) { lockId = (int)lockId + 1; actions = SessionStateActions.None; var update = Update.Set("lockDate", DateTime.Now).Set("lockId", (int)lockId).Set("locked", true).Set("sessionStateActions", SessionStateActions.None); this.mongoCollection.Update(query, update); } if (actions == SessionStateActions.InitializeItem) { return(this.CreateNewStoreData(context, this.sessionStateSection.Timeout.Minutes)); } using (var memoryStream = new MemoryStream(bsonDocument["sessionStateItems"].AsByteArray)) { var sessionStateItems = new SessionStateItemCollection(); if (memoryStream.Length > 0) { var binaryReader = new BinaryReader(memoryStream); sessionStateItems = SessionStateItemCollection.Deserialize(binaryReader); } return(new SessionStateStoreData(sessionStateItems, SessionStateUtility.GetSessionStaticObjects(context), bsonDocument["timeout"].AsInt32)); } }
// // GetSessionStoreItem is called by both the GetItem and // GetItemExclusive methods. GetSessionStoreItem retrieves the // session data from the data source. If the lockRecord parameter // is true (in the case of GetItemExclusive), then GetSessionStoreItem // locks the record and sets a new LockId and LockDate. // private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = 0; // byte array to hold serialized SessionStateItemCollection. byte[] serializedItems = new byte[0]; var sessionStore = new SessionStore(_applicationName); try { Session session = sessionStore.Get(id, this._applicationName); // lockRecord is true when called from GetItemExclusive and // false when called from GetItem. // Obtain a lock if possible. Evict the record if it is expired. if (session == null) { // Not found. The locked value is false. locked = false; } else if (session.Expires < DateTime.Now) { locked = false; sessionStore.EvictSession(session); } else if (session.Locked) { locked = true; lockAge = DateTime.Now.Subtract(session.LockDate); lockId = session.LockID; } else { locked = false; lockId = session.LockID; actionFlags = (SessionStateActions)session.Flags; if (lockRecord) { lockId = (int)lockId + 1; session.LockID = lockId; session.Flags = 0; sessionStore.LockSession(session); } if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, sessionStateSection.Timeout.Minutes); } else { item = Deserialize(context, session.SessionItems.Bytes, session.Timeout); } } } catch (MongoConnectionException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "GetSessionStoreItem"); throw new ProviderException(e.Message, e.InnerException); } else { throw e; } } return(item); }
/// <summary> /// Returns read-only session-state data from the session data store. /// </summary> /// <param name="context">The HttpContext for the current request.</param> /// <param name="id">The SessionID for the current request.</param> /// <param name="locked">When this method returns, contains a Boolean value that is set to true if the requested session item is locked at the session data store; otherwise, false.</param> /// <param name="lockAge">When this method returns, contains a TimeSpan object that is set to the amount of time that an item in the session data store has been locked.</param> /// <param name="lockId">When this method returns, contains an object that is set to the lock identifier for the current request. For details on the lock identifier, see "Locking Session-Store Data" in the SessionStateStoreProviderBase class summary.</param> /// <param name="actions">When this method returns, contains one of the SessionStateActions values, indicating whether the current session is an uninitialized, cookieless session.</param> /// <returns>A SessionStateStoreData populated with session values and information from the session data store.</returns> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { // Initial values for return value and out parameters SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actions = 0; // String to hold serialized SessionStateItemCollection byte[] serializedItems = null; // True if a record is found in the database bool foundRecord = false; // Timeout value from the data store int timeout = 0; var cacheKey = string.Format(_cacheKey, id, _applicationName); var now = DateTime.UtcNow; // Get the current session DacheSessionState currentSession = null; _cacheClient.TryGet <DacheSessionState>(cacheKey, out currentSession); if (currentSession != null) { if (currentSession.Expires < now) { // The record was expired - mark it as not locked locked = false; // Delete the current session _cacheClient.Remove(cacheKey); } else { foundRecord = true; } serializedItems = currentSession.SessionItems; lockId = currentSession.LockId; lockAge = now.Subtract(currentSession.LockDate); actions = currentSession.Flags; timeout = currentSession.Timeout; } // If the record was found and you obtained a lock, then set the lockId, clear the actions, and create the SessionStateStoreItem to return. if (foundRecord && !locked) { var incrementedLockId = (int)lockId + 1; lockId = incrementedLockId; currentSession.LockId = incrementedLockId; currentSession.Flags = SessionStateActions.None; // If the actions parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. if (actions == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, (int)_sessionStateSection.Timeout.TotalMinutes); } else { var sessionItems = new SessionStateItemCollection(); // Deserialize using (var memoryStream = new MemoryStream(serializedItems)) { if (memoryStream.Length > 0) { using (var reader = new BinaryReader(memoryStream)) { sessionItems = SessionStateItemCollection.Deserialize(reader); } } } item = new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), timeout); } } return(item); }
public SessionStateStoreData GetItemImpl(bool exclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { try { using (new LifetimeTimer(_log, "GetItemImpl", 25)) using (var transaction = _datastore.BeginTransaction(_callSettings)) { // Look up both entities in datastore. var entities = transaction.Lookup(new Key[] { _sessionKeyFactory.CreateKey(id), _lockKeyFactory.CreateKey(id) }, _callSettings); SessionLockEntity sessionLock = SessionLockFromEntity(entities[1]); if (sessionLock == null || sessionLock.ExpirationDate < DateTime.UtcNow) { // No such session. lockAge = TimeSpan.Zero; locked = false; lockId = null; actions = SessionStateActions.None; return(null); } SessionEntity sessionItems = SessionFromEntity(id, entities[0]); sessionLock.Items = sessionItems.Items; locked = sessionLock.LockCount > sessionItems.ReleaseCount; lockAge = locked ? DateTime.UtcNow - sessionLock.DateLocked : TimeSpan.Zero; lockId = sessionLock; actions = SessionStateActions.None; if (locked) { return(null); } if (exclusive) { // Lock the session. sessionLock.LockCount = sessionItems.ReleaseCount + 1; sessionLock.DateLocked = DateTime.UtcNow; sessionLock.ExpirationDate = DateTime.UtcNow.AddMinutes(sessionLock.TimeOutInMinutes); transaction.Upsert(ToEntity(sessionLock)); transaction.Commit(_callSettings); locked = true; } return(Deserialize(context, sessionItems.Items, sessionLock.TimeOutInMinutes)); } } catch (Exception e) { _log.Error("GetItemImpl()", e); locked = true; lockAge = TimeSpan.Zero; lockId = 0; actions = SessionStateActions.None; return(null); } }
/// <summary> /// This method returns a read-only session item from the database. /// </summary> public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { return(GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions)); }
private SessionStateStoreData GetItemFromSessionStore(bool isWriteLockRequired, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { try { SessionStateStoreData sessionStateStoreData = null; locked = false; lockAge = TimeSpan.Zero; lockId = 0; actions = SessionStateActions.None; GetAccessToStore(id); ISessionStateItemCollection sessionData = null; int sessionTimeout; bool isLockTaken = false; //Take read or write lock and if locking successful than get data in sessionData and also update session timeout if (isWriteLockRequired) { isLockTaken = cache.TryTakeWriteLockAndGetData(DateTime.Now, (int)configuration.RequestTimeout.TotalSeconds, out lockId, out sessionData, out sessionTimeout); sessionId = id; // signal that we have to remove lock in EndRequest sessionLockId = lockId; // save lockId for EndRequest } else { isLockTaken = cache.TryCheckWriteLockAndGetData(out lockId, out sessionData, out sessionTimeout); } if (isLockTaken) { locked = false; LogUtility.LogInfo("GetItemFromSessionStore => Session Id: {0}, Session provider object: {1} => Lock taken with lockId: {2}", id, this.GetHashCode(), lockId); } else { sessionId = null; sessionLockId = null; locked = true; LogUtility.LogInfo("GetItemFromSessionStore => Session Id: {0}, Session provider object: {1} => Can not lock, Someone else has lock and lockId is {2}", id, this.GetHashCode(), lockId); } // If locking is not successful then do not return any result just return lockAge, locked=true and lockId. // ASP.NET tries to acquire lock again in 0.5 sec by calling this method again. Using lockAge it finds if // lock has been taken more than http request timeout than ASP.NET calls ReleaseItemExclusive and calls this method again to get lock. if (locked) { lockAge = cache.GetLockAge(lockId); return(null); } if (sessionData == null) { // If session data do not exists means it might be exipred and removed. So return null so that asp.net can call CreateUninitializedItem and start again. // But we just locked the record so first release it ReleaseItemExclusive(context, id, lockId); return(null); } // Restore action flag from session data if (sessionData["SessionStateActions"] != null) { actions = (SessionStateActions)sessionData["SessionStateActions"]; } //Get data related to this session from sessionDataDictionary and populate session items sessionData.Dirty = false; sessionStateStoreData = new SessionStateStoreData(sessionData, new HttpStaticObjectsCollection(), sessionTimeout); return(sessionStateStoreData); } catch (Exception e) { LogUtility.LogError("GetItemFromSessionStore => {0}", e.ToString()); locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = 0; LastException = e; if (configuration.ThrowOnError) { throw; } return(null); } }
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { LogUtility.LogInfo("GetItemExclusive => Session Id: {0}, Session provider object: {1}.", id, this.GetHashCode()); return(GetItemFromSessionStore(true, context, id, out locked, out lockAge, out lockId, out actions)); }
SessionStateStoreData GetItemInternal(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; if (id == null) { return(null); } Cache cache = HttpRuntime.InternalCache; string CacheId = CachePrefix + id; InProcSessionItem item = cache [CacheId] as InProcSessionItem; if (item == null) { return(null); } bool readLocked = false, writeLocked = false; try { if (item.rwlock.TryEnterUpgradeableReadLock(lockAcquireTimeout)) { readLocked = true; } else { throw new ApplicationException("Failed to acquire lock"); } if (item.locked) { locked = true; lockAge = DateTime.UtcNow.Subtract(item.lockedTime); lockId = item.lockId; return(null); } if (exclusive) { if (item.rwlock.TryEnterWriteLock(lockAcquireTimeout)) { writeLocked = true; } else { throw new ApplicationException("Failed to acquire lock"); } item.locked = true; item.lockedTime = DateTime.UtcNow; item.lockId++; lockId = item.lockId; } if (item.items == null) { actions = SessionStateActions.InitializeItem; item.items = new SessionStateItemCollection(); } if (item.staticItems == null) { item.staticItems = staticObjects; } return(new SessionStateStoreData(item.items, item.staticItems, item.timeout)); } catch { // we want such errors to be passed to the application. throw; } finally { if (writeLocked) { item.rwlock.ExitWriteLock(); } if (readLocked) { item.rwlock.ExitUpgradeableReadLock(); } } }
/// <summary> /// Returns read-only session-state data from the session data store. /// </summary> /// <param name="context">The HttpContext for the current request.</param> /// <param name="id">The SessionID for the current request.</param> /// <param name="locked">When this method returns, contains a Boolean value that is set to true if a lock is successfully obtained; otherwise, false.</param> /// <param name="lockAge">When this method returns, contains a TimeSpan object that is set to the amount of time that an item in the session data store has been locked.</param> /// <param name="lockId">When this method returns, contains an object that is set to the lock identifier for the current request. For details on the lock identifier, see "Locking Session-Store Data" in the SessionStateStoreProviderBase class summary.</param> /// <param name="actions">When this method returns, contains one of the SessionStateActions values, indicating whether the current session is an uninitialized, cookieless session.</param> /// <returns>A SessionStateStoreData populated with session values and information from the session data store.</returns> public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { var cacheKey = string.Format(_cacheKey, id, _applicationName); var now = DateTime.UtcNow; // Get the current session DacheSessionState currentSession = null; _cacheClient.TryGet <DacheSessionState>(cacheKey, out currentSession); // Obtain a lock if possible. Ignore the record if it is expired. // TODO: this isn't actually thread safe due to a lack of "global" lock // Set locked to true if the record was not updated and false if it was locked = !(currentSession != null && !currentSession.Locked && currentSession.Expires > now); if (!locked) { currentSession.Locked = true; currentSession.LockDate = now; _cacheClient.AddOrUpdate(cacheKey, currentSession); } return(GetItem(context, id, out locked, out lockAge, out lockId, out actions)); }
/// <summary> /// GetSessionStoreItem is called by both the GetItem and GetItemExclusive methods. GetSessionStoreItem /// retrieves the session data from the data source. If the lockRecord parameter is true (in the case of /// GetItemExclusive), then GetSessionStoreItem locks the record and sets a New LockId and LockDate. /// </summary> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = SessionStateActions.None; // MySqlCommand for database commands. MySqlCommand cmd = null; // serialized SessionStateItemCollection. byte[] serializedItems = null; // True if a record is found in the database. bool foundRecord = false; // True if the returned session item is expired and needs to be deleted. bool deleteData = false; // Timeout value from the data store. int timeout = 0; try { using (MySqlConnection conn = new MySqlConnection(connectionString)) { conn.Open(); // lockRecord is True when called from GetItemExclusive and // False when called from GetItem. // Obtain a lock if possible. Ignore the record if it is expired. if (lockRecord) { cmd = new MySqlCommand( "UPDATE my_aspnet_sessions SET " + " Locked = 1, LockDate = NOW()" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND" + " Locked = 0 AND Expires > NOW()", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); if (cmd.ExecuteNonQuery() == 0) { // No record was updated because the record was locked or not found. locked = true; } else { // The record was updated. locked = false; } } // Retrieve the current session item information. cmd = new MySqlCommand( "SELECT NOW(), Expires , SessionItems, LockId, Flags, Timeout, " + " LockDate " + " FROM my_aspnet_sessions" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); // Retrieve session item data from the data source. using (MySqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { DateTime now = reader.GetDateTime(0); DateTime expires = reader.GetDateTime(1); if (now.CompareTo(expires) > 0) { //The record was expired. Mark it as not locked. locked = false; // The session was expired. Mark the data for deletion. deleteData = true; } else { foundRecord = true; } object items = reader.GetValue(2); serializedItems = (items is DBNull) ? null : (byte[])items; lockId = reader.GetValue(3); if (lockId is DBNull) lockId = (int)0; actionFlags = (SessionStateActions)(reader.GetInt32(4)); timeout = reader.GetInt32(5); DateTime lockDate = reader.GetDateTime(6); lockAge = now.Subtract(lockDate); } } //If the returned session item is expired, // delete the record from the data source. if (deleteData) { cmd = new MySqlCommand("DELETE FROM my_aspnet_sessions" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); cmd.ExecuteNonQuery(); } // The record was not found. Ensure that locked is false. if (!foundRecord) locked = false; // If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { lockId = (int)(lockId) + 1; cmd = new MySqlCommand("UPDATE my_aspnet_sessions SET" + " LockId = @LockId, Flags = 0 " + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@LockId", lockId); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); cmd.ExecuteNonQuery(); // If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, (int)sessionStateConfig.Timeout.TotalMinutes); } else { item = Deserialize(context, serializedItems, timeout); } } } } catch (MySqlException e) { HandleMySqlException(e, "GetSessionStoreItem"); } return item; }
public abstract SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions);
/// <summary> /// Get the session for DynamoDB and optionally lock the record. /// </summary> /// <param name="lockRecord"></param> /// <param name="context"></param> /// <param name="sessionId"></param> /// <param name="locked"></param> /// <param name="lockAge"></param> /// <param name="lockId"></param> /// <param name="actionFlags"></param> /// <returns></returns> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string sessionId, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = Guid.NewGuid().ToString(); locked = false; actionFlags = SessionStateActions.None; bool foundRecord = false; bool deleteData = false; DateTime newLockedDate = DateTime.Now; Document doc = null; if (lockRecord) { Document lockDoc = new Document(); lockDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); lockDoc[ATTRIBUTE_LOCK_ID] = lockId.ToString(); lockDoc[ATTRIBUTE_SEQUENCE_ID] = 0; lockDoc[ATTRIBUTE_LOCKED] = true; lockDoc[ATTRIBUTE_LOCK_DATE] = DateTime.Now; try { doc = this._table.UpdateItem(lockDoc, LOCK_UPDATE_CONFIG); locked = false; } catch (ConditionalCheckFailedException) { // This means the record is already locked by another request. locked = true; } } if (doc == null) { doc = this._table.GetItem(GetHashKey(sessionId), 0, CONSISTENT_READ_GET); if (doc == null && lockRecord) { locked = true; } } List<string> serializedItems = new List<string>(); if (doc != null) { DateTime expire = (DateTime)doc[ATTRIBUTE_EXPIRES]; if (expire < DateTime.Now) { deleteData = true; locked = false; } else { foundRecord = true; DynamoDBEntry rootEntry; if (doc.TryGetValue(ATTRIBUTE_SESSION_ITEMS, out rootEntry)) { serializedItems.Add((string)rootEntry); } if (doc.Contains(ATTRIBUTE_LOCK_ID)) lockId = (string)doc[ATTRIBUTE_LOCK_ID]; if (doc.Contains(ATTRIBUTE_FLAGS)) actionFlags = (SessionStateActions)((int)doc[ATTRIBUTE_FLAGS]); if (doc[ATTRIBUTE_LOCK_DATE] != null) { DateTime lockDate = (DateTime)doc[ATTRIBUTE_LOCK_DATE]; lockAge = DateTime.Now.Subtract(lockDate); } if (_shard) { Search search = SearchShards(sessionId); do { List<Document> page = search.GetNextSet(); foreach (var shard in page) { string hash = shard[ATTRIBUTE_SESSION_ID]; int range = int.Parse(shard[ATTRIBUTE_SEQUENCE_ID]); var child = this._table.GetItem(hash, range, CONSISTENT_READ_GET); DynamoDBEntry childEntry; if (child.TryGetValue(ATTRIBUTE_SESSION_ITEMS, out childEntry)) { serializedItems.Add((string)childEntry); } } } while (!search.IsDone); } } } if (deleteData) { this.deleteItem(sessionId); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; lockId = null; } // If the record was found and you obtained a lock, then clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { if (actionFlags == SessionStateActions.InitializeItem) { Document updateDoc = new Document(); updateDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); updateDoc[ATTRIBUTE_FLAGS] = 0; this._table.UpdateItem(updateDoc); item = CreateNewStoreData(context, (int)this._timeout.TotalMinutes); } else { item = deserialize(context, serializedItems.ToArray(), (int)this._timeout.TotalMinutes); } } return item; }
// we don't use the retry policy itself in this function because out parameters are not well handled by // retry policies private SessionStateStoreData GetSession(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { Debug.Assert(context != null); SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id"); SessionRow session = null; int curRetry = 0; bool retry = false; // Assign default values to out parameters locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = SessionStateActions.None; do { retry = false; try { TableServiceContext svc = CreateDataServiceContext(); session = GetSession(id, svc); // Assign default values to out parameters locked = false; lockId = null; lockAge = TimeSpan.Zero; actions = SessionStateActions.None; // if the blob does not exist, we return null // ASP.NET will call the corresponding method for creating the session if (session == null) { return(null); } if (session.Initialized == false) { Debug.Assert(session.Locked == false); actions = SessionStateActions.InitializeItem; session.Initialized = true; } session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout); if (exclusive) { if (!session.Locked) { if (session.Lock == Int32.MaxValue) { session.Lock = 0; } else { session.Lock++; } session.LockDateUtc = DateTime.UtcNow; } lockId = session.Lock; locked = session.Locked; session.Locked = true; } lockAge = DateTime.UtcNow.Subtract(session.LockDateUtc); lockId = session.Lock; if (locked == true) { return(null); } // let's try to write this back to the data store // in between, someone else could have written something to the store for the same session // we retry a number of times; if all fails, we throw an exception svc.UpdateObject(session); svc.SaveChangesWithRetries(); } catch (InvalidOperationException e) { // precondition fails indicates problems with the status code if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.PreconditionFailed) { retry = true; } else { throw new ProviderException("Error accessing the data store.", e); } } } while (retry && curRetry++ < NumRetries); // ok, now we have successfully written back our state // we can now read the blob // note that we do not need to care about read/write locking when accessing the // blob because each time we write a new session we create a new blob with a different name SessionStateStoreData result = null; MemoryStream stream = null; StreamReader reader = null; BlobProperties properties; try { try { stream = _blobProvider.GetBlobContent(session.BlobName, out properties); } catch (Exception e) { throw new ProviderException("Couldn't read session blob!", e); } reader = new StreamReader(stream); if (actions == SessionStateActions.InitializeItem) { // Return an empty SessionStateStoreData result = new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), session.Timeout); } else { // Read Items, StaticObjects, and Timeout from the file byte[] items = Convert.FromBase64String(reader.ReadLine()); byte[] statics = Convert.FromBase64String(reader.ReadLine()); int timeout = session.Timeout; // Deserialize the session result = DeserializeSession(items, statics, timeout); } } finally { if (stream != null) { stream.Close(); } if (reader != null) { reader.Close(); } } return(result); }
public override SessionStateStoreData GetItemExclusive( HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { Debug.Assert(context != null, "Http context is null"); SecUtility.CheckParameter(ref id, true, true, false, ProvidersConfiguration.MaxStringPropertySizeInChars, "id"); return GetSession(context, id, out locked, out lockAge, out lockId, out actions, true); }
public override SessionStateStoreData GetItemExclusive (HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { EnsureGoodId (id, false); return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, true); }
public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { SessionStateStoreData objItem = null; MemcachedHolder objHolder = this._client.Get <MemcachedHolder>(id); DateTime dSetTime = DateTime.Now; #region Initialized lockAge = TimeSpan.Zero; lockId = null; locked = false; actions = 0; #endregion if (objHolder != null) { if (objHolder.Locked == false) { #region objHolder.LockId++; objHolder.SetTime = dSetTime; // Locking Item for memcached objHolder.Locked = true; this._client.Store(StoreMode.Set, id, objHolder, new TimeSpan(0, 0, 0, 0, _objConfig.Timeout.Milliseconds)); actions = (SessionStateActions)objHolder.ActionFlag; lockId = objHolder.LockId; lockAge = objHolder.LockAge; if (this._bIsDbNone == false) // Saving to Db { using (IDbOperations objDb = DbFactory.CreateDbOperations(_strDbType, _strConn)) { locked = objDb.LockItemWithoutLockId(id, ApplicationName); objDb.LockItem(id, ApplicationName, objHolder.LockId); } } if (actions == SessionStateActions.InitializeItem) { objItem = Common.CreateNewStoreData(context, _objConfig.Timeout.Minutes); } else { objItem = Common.Deserialize(context, objHolder.Content, _objConfig.Timeout.Minutes); } return(objItem); #endregion } else { lockAge = objHolder.LockAge; locked = true; lockId = objHolder.LockId; actions = (SessionStateActions)objHolder.ActionFlag; return(objItem); } } else { if (this._bIsDbNone == false) // Saving to Db { using (IDbOperations objDb = DbFactory.CreateDbOperations(_strDbType, _strConn)) { return(objDb.GetItem(id, ApplicationName, _objConfig.Timeout.Minutes, context, true, out locked, out lockAge, out lockId, out actions)); } } else { return(objItem); } } }
private SessionStateStoreData GetSessionStateStoreData(bool exclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { actions = SessionStateActions.None; lockAge = TimeSpan.Zero; locked = false; lockId = null; var query = Query.And(Query.EQ("applicationVirtualPath", HostingEnvironment.ApplicationVirtualPath), Query.EQ("id", id)); var bsonDocument = this.mongoCollection.FindOneAs<BsonDocument>(query); if (bsonDocument == null) { locked = false; } else if (bsonDocument["expires"].AsDateTime <= DateTime.Now) { locked = false; this.mongoCollection.Remove(Query.And(Query.EQ("applicationVirtualPath", HostingEnvironment.ApplicationVirtualPath), Query.EQ("id", id))); } else if (bsonDocument["locked"].AsBoolean == true) { lockAge = DateTime.Now.Subtract(bsonDocument["lockDate"].AsDateTime); locked = true; lockId = bsonDocument["lockId"].AsInt32; } else { locked = false; lockId = bsonDocument["lockId"].AsInt32; actions = (SessionStateActions)bsonDocument["sessionStateActions"].AsInt32; } if (exclusive) { lockId = (int)lockId + 1; actions = SessionStateActions.None; var update = Update.Set("lockDate", DateTime.Now).Set("lockId", (int)lockId).Set("locked", true).Set("sessionStateActions", SessionStateActions.None); this.mongoCollection.Update(query, update); } if (actions == SessionStateActions.InitializeItem) { return CreateNewStoreData(context, sessionStateSection.Timeout.Minutes); } using (var memoryStream = new MemoryStream(bsonDocument["sessionStateItems"].AsByteArray)) { var sessionStateItems = new SessionStateItemCollection(); if (memoryStream.Length > 0) { var binaryReader = new BinaryReader(memoryStream); sessionStateItems = SessionStateItemCollection.Deserialize(binaryReader); } return new SessionStateStoreData(sessionStateItems, SessionStateUtility.GetSessionStaticObjects(context), bsonDocument["timeout"].AsInt32); } }
private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { SessionStateStoreData result = null; locked = default(bool); lockAge = default(TimeSpan); lockId = null; actions = default(SessionStateActions); var riakResult = _client.Get(ApplicationName, id); if (riakResult.IsSuccess) { var riakObject = riakResult.Value; var riakSessionItem = new RiakSessionItem(riakObject); locked = riakSessionItem.Locked; lockAge = DateTime.Now.Subtract(riakSessionItem.LockDate); lockId = riakSessionItem.LockId; actions = (SessionStateActions) riakSessionItem.Flags; if (riakSessionItem.Expires < DateTime.Now || riakSessionItem.Locked) return null; if (actions == SessionStateActions.InitializeItem) { result = CreateNewStoreData(context, riakSessionItem.Timeout); } else { result = Deserialize(riakSessionItem.SessionStoreItems); } if (lockRecord) { riakSessionItem.Locked = true; _client.Async.Put(riakSessionItem.ToRiakObject(), results => { return; }); } } return result; }
public override SessionStateStoreData GetItem(HttpContext context, string sessionID, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return(GetSessionStoreItem(context, sessionID, out locked, out lockAge, out lockId, out actionFlags)); }
/// <summary> /// Get the session for DynamoDB and optionally lock the record. /// </summary> /// <param name="lockRecord"></param> /// <param name="context"></param> /// <param name="sessionId"></param> /// <param name="locked"></param> /// <param name="lockAge"></param> /// <param name="lockId"></param> /// <param name="actionFlags"></param> /// <returns></returns> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string sessionId, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { LogInfo("GetSessionStoreItem", sessionId, lockRecord, context); // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = Guid.NewGuid().ToString(); locked = false; actionFlags = SessionStateActions.None; bool foundRecord = false; bool deleteData = false; DateTime newLockedDate = DateTime.Now; Document session = null; if (lockRecord) { Document lockDoc = new Document(); lockDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); lockDoc[ATTRIBUTE_LOCK_ID] = lockId.ToString(); lockDoc[ATTRIBUTE_LOCKED] = true; lockDoc[ATTRIBUTE_LOCK_DATE] = DateTime.Now; try { session = this._table.UpdateItem(lockDoc, LOCK_UPDATE_CONFIG); locked = false; } catch (ConditionalCheckFailedException) { // This means the record is already locked by another request. locked = true; } } if (session == null) { session = this._table.GetItem(GetHashKey(sessionId), CONSISTENT_READ_GET); if (session == null && lockRecord) { locked = true; } } string serializedItems = null; if (session != null) { DateTime expire = (DateTime)session[ATTRIBUTE_EXPIRES]; if (expire < DateTime.Now) { deleteData = true; locked = false; } else { foundRecord = true; DynamoDBEntry entry; if (session.TryGetValue(ATTRIBUTE_SESSION_ITEMS, out entry)) { serializedItems = (string)entry; } if (session.Contains(ATTRIBUTE_LOCK_ID)) lockId = (string)session[ATTRIBUTE_LOCK_ID]; if (session.Contains(ATTRIBUTE_FLAGS)) actionFlags = (SessionStateActions)((int)session[ATTRIBUTE_FLAGS]); if (session[ATTRIBUTE_LOCK_DATE] != null) { DateTime lockDate = (DateTime)session[ATTRIBUTE_LOCK_DATE]; lockAge = DateTime.Now.Subtract(lockDate); } } } if (deleteData) { this.deleteItem(sessionId); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; lockId = null; } // If the record was found and you obtained a lock, then clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { if (actionFlags == SessionStateActions.InitializeItem) { Document updateDoc = new Document(); updateDoc[ATTRIBUTE_SESSION_ID] = GetHashKey(sessionId); updateDoc[ATTRIBUTE_FLAGS] = 0; this._table.UpdateItem(updateDoc); item = CreateNewStoreData(context, (int)this._timeout.TotalMinutes); } else { item = deserialize(context, serializedItems, (int)this._timeout.TotalMinutes); } } return item; }
/// <summary> /// GetSessionStoreItem is called by both the GetItem and GetItemExclusive methods. GetSessionStoreItem /// retrieves the session data from the data source. If the lockRecord parameter is true (in the case of /// GetItemExclusive), then GetSessionStoreItem locks the record and sets a New LockId and LockDate. /// </summary> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = SessionStateActions.None; // MySqlCommand for database commands. MySqlCommand cmd = null; // serialized SessionStateItemCollection. byte[] serializedItems = null; // True if a record is found in the database. bool foundRecord = false; // True if the returned session item is expired and needs to be deleted. bool deleteData = false; // Timeout value from the data store. int timeout = 0; try { using (MySqlConnection conn = new MySqlConnection(connectionString)) { conn.Open(); // lockRecord is True when called from GetItemExclusive and // False when called from GetItem. // Obtain a lock if possible. Ignore the record if it is expired. if (lockRecord) { cmd = new MySqlCommand( "UPDATE my_aspnet_Sessions SET " + " Locked = 1, LockDate = NOW()" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId AND" + " Locked = 0 AND Expires > NOW()", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); if (cmd.ExecuteNonQuery() == 0) { // No record was updated because the record was locked or not found. locked = true; } else { // The record was updated. locked = false; } } // Retrieve the current session item information. cmd = new MySqlCommand( "SELECT NOW(), Expires , SessionItems, LockId, Flags, Timeout, " + " LockDate " + " FROM my_aspnet_Sessions" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); // Retrieve session item data from the data source. using (MySqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { DateTime now = reader.GetDateTime(0); DateTime expires = reader.GetDateTime(1); if (now.CompareTo(expires) > 0) { //The record was expired. Mark it as not locked. locked = false; // The session was expired. Mark the data for deletion. deleteData = true; } else { foundRecord = true; } object items = reader.GetValue(2); serializedItems = (items is DBNull) ? null : (byte[])items; lockId = reader.GetValue(3); if (lockId is DBNull) { lockId = (int)0; } actionFlags = (SessionStateActions)(reader.GetInt32(4)); timeout = reader.GetInt32(5); DateTime lockDate = reader.GetDateTime(6); lockAge = now.Subtract(lockDate); } } //If the returned session item is expired, // delete the record from the data source. if (deleteData) { cmd = new MySqlCommand("DELETE FROM my_aspnet_Sessions" + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); cmd.ExecuteNonQuery(); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; } // If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { lockId = (int)(lockId) + 1; cmd = new MySqlCommand("UPDATE my_aspnet_Sessions SET" + " LockId = @LockId, Flags = 0 " + " WHERE SessionId = @SessionId AND ApplicationId = @ApplicationId", conn); cmd.Parameters.AddWithValue("@LockId", lockId); cmd.Parameters.AddWithValue("@SessionId", id); cmd.Parameters.AddWithValue("@ApplicationId", ApplicationId); cmd.ExecuteNonQuery(); // If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, (int)sessionStateConfig.Timeout.TotalMinutes); } else { item = Deserialize(context, serializedItems, timeout); } } } } catch (MySqlException e) { HandleMySqlException(e, "GetSessionStoreItem"); } return(item); }
/// <summary> /// GetSessionStoreItem is called by both the GetItem and /// GetItemExclusive methods. GetSessionStoreItem retrieves the /// session data from the data source. If the lockRecord parameter /// is true (in the case of GetItemExclusive), then GetSessionStoreItem /// locks the record and sets a new LockId and LockDate. /// </summary> private SessionStateStoreData GetSessionStoreItem( bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = 0; MongoClient conn = GetConnection(); var sessionCollection = GetSessionCollection(conn); // DateTime to check if current session item is expired. // String to hold serialized SessionStateItemCollection. BsonArray serializedItems = new BsonArray(); // True if a record is found in the database. bool foundRecord = false; // True if the returned session item is expired and needs to be deleted. bool deleteData = false; // Timeout value from the data store. int timeout = 0; // lockRecord is true when called from GetItemExclusive and // false when called from GetItem. // Obtain a lock if possible. Ignore the record if it is expired. FilterDefinition <BsonDocument> query; if (lockRecord) { query = Builders <BsonDocument> .Filter.And( Builders <BsonDocument> .Filter.Eq("_id", MongoSessionStateStoreHelpers.GetDocumentSessionId(id, ApplicationName)), Builders <BsonDocument> .Filter.Eq("Locked", false), Builders <BsonDocument> .Filter.Gt("Expires", DateTime.Now.ToUniversalTime())); var update = Builders <BsonDocument> .Update.Set("Locked", true) .Set("LockDate", DateTime.Now.ToUniversalTime()); var result = this.UpdateSessionCollection(sessionCollection, query, update); if (result.IsAcknowledged) { locked = result.ModifiedCount == 0; // DocumentsAffected == 0 == No record was updated because the record was locked or not found. } } // Retrieve the current session item information. query = Builders <BsonDocument> .Filter.Eq("_id", MongoSessionStateStoreHelpers.GetDocumentSessionId(id, ApplicationName)); var results = this.FindOneSessionItem(sessionCollection, query); if (results != null) { DateTime expires = results["Expires"].ToUniversalTime(); if (expires < DateTime.Now.ToUniversalTime()) { // The record was expired. Mark it as not locked. locked = false; // The session was expired. Mark the data for deletion. deleteData = true; } else { foundRecord = true; } serializedItems = results["SessionItemJSON"].AsBsonArray; lockId = results["LockId"].AsInt32; lockAge = DateTime.Now.ToUniversalTime().Subtract(results["LockDate"].ToUniversalTime()); actionFlags = (SessionStateActions)results["Flags"].AsInt32; timeout = results["Timeout"].AsInt32; } // If the returned session item is expired, // delete the record from the data source. if (deleteData) { query = Builders <BsonDocument> .Filter.Eq("_id", MongoSessionStateStoreHelpers.GetDocumentSessionId(id, ApplicationName)); this.DeleteSessionDocument(sessionCollection, query); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; } // If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { lockId = (int)lockId + 1; query = Builders <BsonDocument> .Filter.Eq("_id", MongoSessionStateStoreHelpers.GetDocumentSessionId(id, ApplicationName)); var update = Builders <BsonDocument> .Update.Set("LockId", (int)lockId).Set("Flags", 0); this.UpdateSessionCollection(sessionCollection, query, update); // If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. item = actionFlags == SessionStateActions.InitializeItem ? CreateNewStoreData(context, (int)_config.Timeout.TotalMinutes) : MongoSessionStateStoreHelpers.Deserialize(context, serializedItems, timeout); } return(item); }
/// <summary> /// Retrieves session values and information from the session data store and locks the session-item data /// at the data store for the duration of the request. /// </summary> /// <param name="context">The HttpContext instance for the current request</param> /// <param name="id">The session identifier.</param> /// <param name="locked">An output parameter indicating whether the item is currently exclusively locked.</param> /// <param name="lockAge">The age of the exclusive lock (if present)</param> /// <param name="lockId">The identifier of the exclusive lock (if present)</param> /// <param name="actions">Used with sessions whose Cookieless property is true, /// when the regenerateExpiredSessionId attribute is set to true. /// An actionFlags value set to InitializeItem (1) indicates that the entry in the session data store is a /// new session that requires initialization.</param> /// <returns>The session data</returns> public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) { try { Logger.Debug("Beginning GetItemExclusive. SessionId={0}.", id); var item = GetSessionStoreItem(true, context, id, _retriesOnConcurrentConflicts, out locked, out lockAge, out lockId, out actions); Logger.Debug("Completed GetItemExclusive. SessionId={0}, locked={1}, lockAge={2}, lockId={3}, actions={4}.", id, locked, lockAge, lockId, actions); return item; } catch (Exception ex) { Logger.ErrorException(string.Format("Error during GetItemExclusive. SessionId={0}.", id), ex); throw; } }
SessionStateStoreData GetItemInternal (HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; if (id == null) return null; StateServerItem item = stateServer.GetItem (id, out locked, out lockAge, out lockId, out actions, exclusive); if (item == null) return null; if (actions == SessionStateActions.InitializeItem) return CreateNewStoreData (context, item.Timeout); SessionStateItemCollection items = null; HttpStaticObjectsCollection sobjs = null; MemoryStream stream = null; BinaryReader reader = null; Stream input = null; #if NET_4_0 GZipStream gzip = null; #endif try { if (item.CollectionData != null && item.CollectionData.Length > 0) { stream = new MemoryStream (item.CollectionData); #if NET_4_0 if (config.CompressionEnabled) input = gzip = new GZipStream (stream, CompressionMode.Decompress, true); else #endif input = stream; reader = new BinaryReader (input); items = SessionStateItemCollection.Deserialize (reader); #if NET_4_0 if (gzip != null) gzip.Close (); #endif reader.Close (); } else items = new SessionStateItemCollection (); if (item.StaticObjectsData != null && item.StaticObjectsData.Length > 0) sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData); else sobjs = new HttpStaticObjectsCollection (); } catch (Exception ex) { throw new HttpException ("Failed to retrieve session state.", ex); } finally { if (stream != null) stream.Dispose (); #if NET_4_0 if (reader != null) reader.Dispose (); if (gzip != null) gzip.Dispose (); #else if (reader != null) ((IDisposable)reader).Dispose (); #endif } return new SessionStateStoreData (items, sobjs, item.Timeout); }
// // GetSessionStoreItem is called by both the GetItem and // GetItemExclusive methods. GetSessionStoreItem retrieves the // session data from the data source. If the lockRecord parameter // is true (in the case of GetItemExclusive), then GetSessionStoreItem // locks the record and sets a new LockId and LockDate. // private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, int retriesRemaining, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = 0; using (var documentSession = _documentStore.OpenSession()) { //don't tolerate stale data documentSession.Advanced.AllowNonAuthoritiveInformation = false; //if we get a concurrency conflict, then we want to know about it documentSession.Advanced.UseOptimisticConcurrency = true; var sessionState = documentSession.Query<SessionState>() .Customize(x=>x.WaitForNonStaleResultsAsOfLastWrite()) .SingleOrDefault( x => x.SessionId == id && x.ApplicationName == ApplicationName ); if (sessionState == null) return null; //if the record is locked, we can't have it. if (sessionState.Locked) { locked = true; lockAge = DateTime.UtcNow.Subtract((DateTime) sessionState.LockDate); lockId = sessionState.LockId; return null; } //generally we shouldn't get expired items, as the expiration bundle should clean them up, //but just in case the bundle isn't installed, or we made the window, we'll delete expired items here. if (sessionState.Expires < DateTime.UtcNow) { try { documentSession.Delete(sessionState); documentSession.SaveChanges(); } catch (ConcurrencyException) { //we swallow, as we don't care. Presumably the other modifier deleted it as well. } return null; } if (lockRecord) { sessionState.Locked = true; sessionState.LockId += 1; sessionState.LockDate = DateTime.UtcNow; try { documentSession.SaveChanges(); } catch (ConcurrencyException) { if (retriesRemaining > 0) return GetSessionStoreItem(true, context, id, retriesRemaining - 1, out locked, out lockAge, out lockId, out actionFlags); throw; } } lockId = sessionState.LockId; return sessionState.Flags == SessionStateActions.InitializeItem ? new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), _sessionStateConfig.Timeout.Minutes) : Deserialize(context, sessionState.SessionItems, _sessionStateConfig.Timeout.Minutes); } }
private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { locked = false; lockAge = TimeSpan.Zero; lockId = null; actionFlags = 0; SessionStateStoreData item = null; using (FbConnection conn = new FbConnection(this.connectionString)) { DateTime expires; string serializedItems = ""; bool foundRecord = false; bool deleteData = false; int timeout = 0; conn.Open(); if (lockRecord) { using (FbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "UPDATE SESSIONS SET LOCKED = @LOCKED, LOCKDATE = @LOCKDATE " + "WHERE SESSIONID = @SESSIONID AND APPLICATIONNAME = @APPLICATIONNAME AND " + "LOCKED = @LOCKED2 AND EXPIRES > @EXPIRES"; cmd.Parameters.Add("@LOCKED", FbDbType.SmallInt).Value = true; cmd.Parameters.Add("@LOCKDATE", FbDbType.TimeStamp).Value = DateTime.Now; cmd.Parameters.Add("@SESSIONID", FbDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@APPLICATIONNAME", FbDbType.VarChar, 100).Value = ApplicationName; cmd.Parameters.Add("@LOCKED2", FbDbType.Integer).Value = false; cmd.Parameters.Add("@EXPIRES", FbDbType.TimeStamp).Value = DateTime.Now; if (cmd.ExecuteNonQuery() == 0) { locked = true; } else { locked = false; } } } using (FbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT EXPIRES, SESSIONITEMS, LOCKID, LOCKDATE, FLAGS, TIMEOUT " + "FROM SESSIONS WHERE SESSIONID = @SESSIONID AND APPLICATIONNAME = @APPLICATIONNAME"; cmd.Parameters.Add("@SESSIONID", FbDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@APPLICATIONNAME", FbDbType.VarChar, 100).Value = ApplicationName; using (FbDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) { while (reader.Read()) { expires = reader.GetDateTime(0); if (expires < DateTime.Now) { locked = false; deleteData = true; } else { foundRecord = true; } serializedItems = reader.GetString(1); lockId = reader.GetInt32(2); lockAge = DateTime.Now.Subtract(reader.GetDateTime(3)); actionFlags = (SessionStateActions)reader.GetInt32(4); timeout = reader.GetInt32(5); } if (!foundRecord) { locked = false; } } } if (deleteData) { using (FbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "DELETE FROM SESSIONS WHERE SESSIONID = @SESSIONID AND APPLICATIONNAME = @APPLICATIONNAME"; cmd.Parameters.Add("@SESSIONID", FbDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@APPLICATIONNAME", FbDbType.VarChar, 100).Value = ApplicationName; cmd.ExecuteNonQuery(); } } if (foundRecord && !locked) { lockId = (int)lockId + 1; using (FbCommand cmd = conn.CreateCommand()) { cmd.CommandText = "UPDATE SESSIONS SET LOCKID = @LOCKID, FLAGS = 0 " + "WHERE SESSIONID = @SESSIONID AND APPLICATIONNAME = @APPLICATIONNAME"; cmd.Parameters.Add("@LOCKID", FbDbType.Integer).Value = lockId; cmd.Parameters.Add("@SESSIONID", FbDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@APPLICATIONNAME", FbDbType.VarChar, 100).Value = ApplicationName; cmd.ExecuteNonQuery(); } if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, this.config.Timeout.Minutes); } else { item = Deserialize(context, serializedItems, timeout); } } } return(item); }
SessionStateStoreData GetItemInternal (HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions, bool exclusive) { locked = false; lockAge = TimeSpan.MinValue; lockId = Int32.MinValue; actions = SessionStateActions.None; if (id == null) return null; Cache cache = HttpRuntime.InternalCache; string CacheId = CachePrefix + id; InProcSessionItem item = cache [CacheId] as InProcSessionItem; if (item == null) return null; bool readLocked = false, writeLocked = false; try { if (item.rwlock.TryEnterUpgradeableReadLock (lockAcquireTimeout)) readLocked = true; else throw new ApplicationException ("Failed to acquire lock"); if (item.locked) { locked = true; lockAge = DateTime.UtcNow.Subtract (item.lockedTime); lockId = item.lockId; return null; } if (exclusive) { if (item.rwlock.TryEnterWriteLock (lockAcquireTimeout)) writeLocked = true; else throw new ApplicationException ("Failed to acquire lock"); item.locked = true; item.lockedTime = DateTime.UtcNow; item.lockId++; lockId = item.lockId; } if (item.items == null) { actions = SessionStateActions.InitializeItem; item.items = new SessionStateItemCollection (); } if (item.staticItems == null) item.staticItems = staticObjects; return new SessionStateStoreData (item.items, item.staticItems, item.timeout); } catch { // we want such errors to be passed to the application. throw; } finally { if (writeLocked) item.rwlock.ExitWriteLock (); if (readLocked) item.rwlock.ExitUpgradeableReadLock (); } }
/// <summary> /// GetSessionStoreItem is called by both the GetItem and /// GetItemExclusive methods. GetSessionStoreItem retrieves the /// session data from the data source. If the lockRecord parameter /// is true (in the case of GetItemExclusive), then GetSessionStoreItem /// locks the record and sets a new LockId and LockDate. /// </summary> private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = 0; // DateTime to check if current session item is expired. // String to hold serialized SessionStateItemCollection. var serializedItems = ""; // True if a record is found in the database. var foundRecord = false; // True if the returned session item is expired and needs to be deleted. var deleteData = false; // Timeout value from the data store. var timeout = 0; IMongoQuery query = null; var cTime = DateTime.UtcNow; try { MongoCollection sessionCollection = GetSessionCollection(); // lockRecord is true when called from GetItemExclusive and // false when called from GetItem. // Obtain a lock if possible. Ignore the record if it is expired. if (lockRecord) { query = Query.And(Query.EQ("_id", id), Query.EQ("App", ApplicationName), Query.EQ("Locked", false), Query.GT("Expires", cTime)); var update = Update.Set("Locked", true); update.Set("LockDate", cTime); var result = sessionCollection.Update(query, update); if (result.DocumentsAffected == 0) { // No record was updated because the record was locked or not found. locked = true; } } // Retrieve the current session item information. query = Query.And(Query.EQ("_id", id), Query.EQ("App", ApplicationName)); var results = sessionCollection.FindOneAs <BsonDocument>(query); if (results != null) { var expires = results["Expires"].AsDateTime; if (expires < cTime) { // The record was expired. Mark it as not locked. locked = false; // The session was expired. Mark the data for deletion. deleteData = true; } else { foundRecord = true; } serializedItems = results["Items"].AsString; lockId = results["LockId"].AsInt32; lockAge = cTime.Subtract(results["LockDate"].AsDateTime); actionFlags = (SessionStateActions)results["Flags"].AsInt32; timeout = results["Timeout"].AsInt32; } // If the returned session item is expired, // delete the record from the data source. if (deleteData) { query = Query.And(Query.EQ("_id", id), Query.EQ("App", ApplicationName)); sessionCollection.Remove(query, writeMode); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; } // If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { lockId = (int)lockId + 1; query = Query.And(Query.EQ("_id", id), Query.EQ("App", ApplicationName)); var update = Update.Set("LockId", (int)lockId); update.Set("Flags", 0); sessionCollection.Update(query, update, writeMode); // If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, (int)config.Timeout.TotalMinutes); } else { item = Deserialize(context, serializedItems, timeout); } } } catch (Exception e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "GetSessionStoreItem"); throw new ProviderException(ExceptionMessage); } throw; } return(item); }
/// <summary> /// GetItemおよびGetItemExclusiveの両方によって呼ばれ、 /// セッション データ ストアを検索する。 /// lockRecordパラメーターがtrueの場合 /// (GetItemExclusiveから呼ばれた場合)、 /// セッション データ ストア項目をロックし、 /// 新しいLockIdおよびLockDateをセットする。 /// </summary> /// <param name="lockRecord"> /// GetItemExclusiveから呼ばれた場合、true /// GetItemから呼ばれた場合、false /// </param> /// <param name="context"> /// HttpContext /// </param> /// <param name="id"> /// セッション識別子 /// </param> /// <param name="locked"> /// 要求したセッション項目が /// セッション データ ストアで /// ・ロックされているときはブール値 true /// ・それ以外の場合は false /// </param> /// <param name="lockAge"> /// セッション データ ストアの項目がロック /// された時間に設定された TimeSpan オブジェクト /// </param> /// <param name="lockId"> /// ロック識別子 /// </param> /// <param name="actionFlags"> /// 現在のセッションが初期化されていない /// cookieless セッションかどうかを示す /// SessionStateActions 値 /// </param> /// <returns> /// SessionStateStoreData /// </returns> private SessionStateStoreData GetSessionStoreItem( bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { // Initial values for return value and out parameters. SessionStateStoreData item = null; lockAge = TimeSpan.Zero; lockId = null; locked = false; actionFlags = 0; // Sql database connection. SqlConnection conn = new SqlConnection(this.ConnectionString); // SqlCommand for database commands. SqlCommand cmd = null; // DataReader to read database record. SqlDataReader reader = null; // DateTime to check if current session item is expired. DateTime expires; // String to hold serialized SessionStateItemCollection. string serializedItems = ""; // True if a record is found in the database. bool foundRecord = false; // True if the returned session item is expired and needs to be deleted. bool deleteData = false; // Timeout value from the data store. int timeout = 0; try { conn.Open(); if (lockRecord) { cmd = new SqlCommand( "UPDATE ASPStateSessions SET" + " Locked = @Locked, LockDate = @LockDate " + " WHERE SessionId = @SessionId AND ApplicationName = @ApplicationName AND Locked = @Locked2 AND Expires > @Expires", conn); cmd.Parameters.Add("@Locked", SqlDbType.Bit).Value = true; cmd.Parameters.Add("@LockDate", SqlDbType.DateTime).Value = DateTime.Now; cmd.Parameters.Add("@SessionId", SqlDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@ApplicationName", SqlDbType.VarChar, 255).Value = ApplicationName; cmd.Parameters.Add("@Locked2", SqlDbType.Int).Value = false; cmd.Parameters.Add ("@Expires", SqlDbType.DateTime).Value = DateTime.Now; if (cmd.ExecuteNonQuery() == 0) { // No record was updated because the record was locked or not found. locked = true; } else { // The record was updated. locked = false; } } // Retrieve the current session item information. cmd = new SqlCommand( "SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout " + " FROM ASPStateSessions " + " WHERE SessionId = @SessionId AND ApplicationName = @ApplicationName", conn); cmd.Parameters.Add("@SessionId", SqlDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@ApplicationName", SqlDbType.VarChar, 255).Value = ApplicationName; // Retrieve session item data from the data source. reader = cmd.ExecuteReader(CommandBehavior.SingleRow); while (reader.Read()) { expires = reader.GetDateTime(0); if (expires < DateTime.Now) { // The record was expired. Mark it as not locked. locked = false; // The session was expired. Mark the data for deletion. deleteData = true; } else { foundRecord = true; } serializedItems = reader.GetString(1); lockId = reader.GetInt32(2); lockAge = DateTime.Now.Subtract(reader.GetDateTime(3)); actionFlags = (SessionStateActions)reader.GetInt32(4); timeout = reader.GetInt32(5); } reader.Close(); // If the returned session item is expired, // delete the record from the data source. if (deleteData) { cmd = new SqlCommand("DELETE FROM ASPStateSessions " + "WHERE SessionId = @SessionId AND ApplicationName = @ApplicationName", conn); cmd.Parameters.Add("@SessionId", SqlDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@ApplicationName", SqlDbType.VarChar, 255).Value = ApplicationName; cmd.ExecuteNonQuery(); } // The record was not found. Ensure that locked is false. if (!foundRecord) { locked = false; } // If the record was found and you obtained a lock, then set // the lockId, clear the actionFlags, // and create the SessionStateStoreItem to return. if (foundRecord && !locked) { lockId = (int)lockId + 1; cmd = new SqlCommand("UPDATE ASPStateSessions SET" + " LockId = @LockId, Flags = 0 " + " WHERE SessionId = @SessionId AND ApplicationName = @ApplicationName", conn); cmd.Parameters.Add("@LockId", SqlDbType.Int).Value = lockId; cmd.Parameters.Add("@SessionId", SqlDbType.VarChar, 80).Value = id; cmd.Parameters.Add("@ApplicationName", SqlDbType.VarChar, 255).Value = ApplicationName; cmd.ExecuteNonQuery(); // If the actionFlags parameter is not InitializeItem, // deserialize the stored SessionStateItemCollection. if (actionFlags == SessionStateActions.InitializeItem) { item = CreateNewStoreData(context, Convert.ToInt32(this._sessionStateConfig.Timeout.TotalMinutes)); } else { item = Deserialize(context, serializedItems, timeout); } } } catch (SqlException e) { if (WriteExceptionsToEventLog) { WriteToEventLog(e, "GetSessionStoreItem"); throw new ProviderException(EXCEPTION_MESSAGE); } else { throw; } } finally { if (reader != null) { reader.Close(); } conn.Close(); } return(item); }