Exemple #1
0
        /// <inheritdoc />
        public override Task CreateUninitializedItemAsync(
            HttpContextBase context,
            string id,
            int timeout,
            CancellationToken cancellationToken)
        {
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }
            if (id.Length > SessionIDManager.SessionIDMaxLength)
            {
                throw new ArgumentException(SR.Session_id_too_long);
            }

            var state = new InProcSessionState(
                null,
                null,
                timeout,
                false,
                DateTime.MinValue,
                NewLockCookie,
                (int)SessionStateItemFlags.Uninitialized);

            InsertToCache(id, state);

            return(Task.CompletedTask);
        }
Exemple #2
0
        private void InsertToCache(string key, InProcSessionState value)
        {
            var cachePolicy = new CacheItemPolicy()
            {
                SlidingExpiration = new TimeSpan(0, value.Timeout, 0),
                RemovedCallback   = _callback,
                Priority          = CacheItemPriority.NotRemovable
            };

            s_store.Set(key, value, cachePolicy);
        }
Exemple #3
0
        private SessionStateStoreData DoGet(HttpContextBase context,
                                            String id,
                                            bool exclusive,
                                            out bool locked,
                                            out TimeSpan lockAge,
                                            out object lockId,
                                            out SessionStateActions actionFlags)
        {
            // Set default return values
            locked      = false;
            lockId      = null;
            lockAge     = TimeSpan.Zero;
            actionFlags = 0;

            InProcSessionState state = (InProcSessionState)s_store.Get(id);

            if (state != null)
            {
                bool lockedByOther;       // True if the state is locked by another session
                int  initialFlags;

                initialFlags = state.Flags;
                if ((initialFlags & (int)SessionStateItemFlags.Uninitialized) != 0)
                {
                    // It is an uninitialized item.  We have to remove that flag.
                    // We only allow one request to do that.
                    // If initialFlags != return value of CompareExchange, it means another request has
                    // removed the flag.

                    if (initialFlags == Interlocked.CompareExchange(
                            ref state.Flags,
                            initialFlags & (~((int)SessionStateItemFlags.Uninitialized)),
                            initialFlags))
                    {
                        actionFlags = SessionStateActions.InitializeItem;
                    }
                }

                if (exclusive)
                {
                    lockedByOther = true;

                    // If unlocked, use a spinlock to test and lock the state.
                    if (!state.Locked)
                    {
                        var lockTaken = false;
                        try
                        {
                            state.SpinLock.Enter(ref lockTaken);

                            if (!state.Locked)
                            {
                                lockedByOther  = false;
                                state.Locked   = true;
                                state.LockDate = DateTime.UtcNow;
                                state.LockCookie++;
                            }
                            lockId = state.LockCookie;
                        }
                        finally
                        {
                            if (lockTaken)
                            {
                                state.SpinLock.Exit();
                            }
                        }
                    }
                    else
                    {
                        // It's already locked by another request.  Return the lockCookie to caller.
                        lockId = state.LockCookie;
                    }
                }
                else
                {
                    var lockTaken = false;
                    state.SpinLock.Enter(ref lockTaken);
                    try
                    {
                        lockedByOther = state.Locked;
                        lockId        = state.LockCookie;
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            state.SpinLock.Exit();
                        }
                    }
                }

                if (lockedByOther)
                {
                    // Item found, but locked
                    locked  = true;
                    lockAge = DateTime.UtcNow - state.LockDate;
                    return(null);
                }
                else
                {
                    return(CreateLegitStoreData(context, state.SessionItems, state.StaticObjects, state.Timeout));
                }
            }

            // Not found
            return(null);
        }
Exemple #4
0
        /// <inheritdoc />
        public override Task SetAndReleaseItemExclusiveAsync(
            HttpContextBase context,
            string id,
            SessionStateStoreData item,
            object lockId,
            bool newItem,
            CancellationToken cancellationToken)
        {
            if (id == null)
            {
                throw new ArgumentNullException("id");
            }
            if (id.Length > SessionIDManager.SessionIDMaxLength)
            {
                throw new ArgumentException(SR.Session_id_too_long);
            }

            Debug.Assert(item != null, "item != null");
            Debug.Assert(item.StaticObjects != null, "item.StaticObjects != null");

            ISessionStateItemCollection items         = null;
            HttpStaticObjectsCollection staticObjects = null;
            var doInsert            = true;
            var lockCookieForInsert = NewLockCookie;

            if (item.Items.Count > 0)
            {
                items = item.Items;
            }

            if (!item.StaticObjects.NeverAccessed)
            {
                staticObjects = item.StaticObjects;
            }

            if (!newItem)
            {
                var currentState = (InProcSessionState)s_store.Get(id);
                var lockCookie   = (int)lockId;

                if (currentState == null)
                {
                    return(Task.CompletedTask);
                }

                var lockTaken = false;
                try
                {
                    currentState.SpinLock.Enter(ref lockTaken);

                    // we can change the state in place if the timeout hasn't changed
                    if (currentState.Timeout == item.Timeout)
                    {
                        currentState.Copy(items, staticObjects, item.Timeout, false, DateTime.MinValue, lockCookie, currentState.Flags);

                        doInsert = false;
                    }
                    else
                    {
                        /* We are going to insert a new item to replace the current one in Cache
                         * because the expiry time has changed.
                         *
                         * Pleas note that an insert will cause the Session_End to be incorrectly raised.
                         *
                         * Please note that the item itself should not expire between now and
                         * where we do MemoryCache.Insert below because MemoryCache.Get above have just
                         * updated its expiry time.
                         */
                        currentState.Flags |= (int)SessionStateItemFlags.IgnoreCacheItemRemoved;
                        lockCookieForInsert = lockCookie;
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        currentState.SpinLock.Exit();
                    }
                }
            }

            if (doInsert)
            {
                var newState = new InProcSessionState(
                    items,
                    staticObjects,
                    item.Timeout,
                    false,
                    DateTime.MinValue,
                    lockCookieForInsert,
                    0);

                InsertToCache(id, newState);
            }

            return(Task.CompletedTask);
        }