public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockIdObject, bool newItem)
        {
            _log.DebugFormat("SetAndReleaseItemExclusive({0})", id);
            LogExceptions("SetAndReleaseItemExclusive()", () =>
            {
#if DEBUG
                // To test the exception handling code.
                if (null != item.Items["throwthrowthrow"])
                {
                    throw new Exception("throwthrowthrow");
                }
#endif
                SessionLockEntity lockId   = (SessionLockEntity)lockIdObject;
                SessionEntity sessionItems = new SessionEntity();
                sessionItems.Id            = id;
                if (newItem)
                {
                    // Insert new SessionLock and SessionItems.
                    sessionItems.Items            = Serialize((SessionStateItemCollection)item.Items);
                    sessionItems.ReleaseCount     = 0;
                    SessionLockEntity sessionLock = new SessionLockEntity
                    {
                        Id = id,
                        TimeOutInMinutes = item.Timeout,
                        ExpirationDate   = DateTime.UtcNow.AddMinutes(item.Timeout),
                        DateLocked       = DateTime.UtcNow,
                        LockCount        = 0
                    };
                    using (new LifetimeTimer(_log, "SetAndReleaseItemExclusive(new)", 25))
                        using (var transaction = _datastore.BeginTransaction(_callSettings))
                        {
                            transaction.Upsert(ToEntity(sessionItems), ToEntity(sessionLock));
                            transaction.Commit(_callSettings);
                        }
                    return;
                }
                using (new LifetimeTimer(_log, "SetAndReleaseItemExclusive", 25))
                    using (var transaction = _datastore.BeginTransaction(_callSettings))
                    {
                        // Update existing session items.
                        sessionItems.Items = item.Items.Dirty ?
                                             Serialize((SessionStateItemCollection)item.Items) : lockId.Items;
                        // Unlock the session.
                        sessionItems.ReleaseCount     = lockId.LockCount;
                        SessionLockEntity sessionLock = SessionLockFromEntity(
                            transaction.Lookup(_lockKeyFactory.CreateKey(id), _callSettings));
                        if (sessionLock == null || sessionLock.LockCount != lockId.LockCount)
                        {
                            return; // Something else locked it in the meantime.
                        }
                        transaction.Upsert(ToEntity(sessionItems));
                        transaction.Commit(_callSettings);
                    }
            });
        }
        /// <summary>
        /// Pack a SessionLock into a Datastore entity.
        /// </summary>
        private Entity ToEntity(SessionLockEntity sessionLock)
        {
            var entity = new Entity();

            entity.Key         = _lockKeyFactory.CreateKey(sessionLock.Id);
            entity[LOCK_COUNT] = sessionLock.LockCount;
            entity[LOCK_DATE]  = sessionLock.DateLocked;
            entity[TIMEOUT]    = sessionLock.TimeOutInMinutes;
            entity[EXPIRES]    = sessionLock.ExpirationDate;
            ExcludeFromIndexes(entity, LOCK_COUNT, LOCK_DATE, TIMEOUT);
            return(entity);
        }
        /// <summary>
        /// Unpack a SessionLockEntity from a Datastore entity.
        /// </summary>
        /// <param name="entity">The datastore entity.</param>
        /// <returns>A SessionLock instance.  Returns null if entity is null.</returns>
        private SessionLockEntity SessionLockFromEntity(Entity entity)
        {
            if (null == entity)
            {
                return(null);
            }
            SessionLockEntity sessionLock = new SessionLockEntity();

            sessionLock.Id               = entity.Key.Path.First().Name;
            sessionLock.LockCount        = (int)entity[LOCK_COUNT];
            sessionLock.DateLocked       = (DateTime)entity[LOCK_DATE];
            sessionLock.ExpirationDate   = (DateTime)entity[EXPIRES];
            sessionLock.TimeOutInMinutes = (int)entity[TIMEOUT];
            return(sessionLock);
        }
 public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
 {
     _log.DebugFormat("CreateUninitializedItem({0})", id);
     LogExceptions("CreateUninitializedItem()", () =>
     {
         var sessionLock              = new SessionLockEntity();
         sessionLock.Id               = id;
         sessionLock.ExpirationDate   = DateTime.UtcNow.AddMinutes(timeout);
         sessionLock.TimeOutInMinutes = timeout;
         sessionLock.DateLocked       = DateTime.UtcNow;
         sessionLock.LockCount        = 0;
         using (new LifetimeTimer(_log, "CreateUninitializedItem", 25))
             using (var transaction = _datastore.BeginTransaction(_callSettings))
             {
                 transaction.Upsert(ToEntity(sessionLock));
                 transaction.Delete(_sessionKeyFactory.CreateKey(id));
                 transaction.Commit(_callSettings);
             }
     });
 }
 public override void RemoveItem(HttpContext context, string id, object lockIdObject,
                                 SessionStateStoreData item)
 {
     _log.DebugFormat("RemoveItem({0})", id);
     LogExceptions("RemoveItem()", () =>
     {
         SessionLockEntity lockId = (SessionLockEntity)lockIdObject;
         using (new LifetimeTimer(_log, "RemoveItem", 25))
             using (var transaction = _datastore.BeginTransaction(_callSettings))
             {
                 SessionLockEntity sessionLock = SessionLockFromEntity(
                     transaction.Lookup(_lockKeyFactory.CreateKey(id), _callSettings));
                 if (sessionLock == null || sessionLock.LockCount != lockId.LockCount)
                 {
                     return; // Something else locked it in the meantime.
                 }
                 transaction.Delete(_sessionKeyFactory.CreateKey(id),
                                    _lockKeyFactory.CreateKey(id));
                 transaction.Commit(_callSettings);
             }
     });
 }
 public override void ReleaseItemExclusive(HttpContext context, string id, object lockIdObject)
 {
     _log.DebugFormat("ReleaseItemExclusive({0})", id);
     LogExceptions("ReleaseItemExclusive()", () =>
     {
         SessionLockEntity lockId   = (SessionLockEntity)lockIdObject;
         SessionEntity sessionItems = new SessionEntity();
         sessionItems.Id            = id;
         sessionItems.ReleaseCount  = lockId.LockCount;
         sessionItems.Items         = lockId.Items;
         using (new LifetimeTimer(_log, "ReleaseItemExclusive", 25))
             using (var transaction = _datastore.BeginTransaction(_callSettings))
             {
                 SessionLockEntity sessionLock = SessionLockFromEntity(
                     transaction.Lookup(_lockKeyFactory.CreateKey(id), _callSettings));
                 if (sessionLock == null || sessionLock.LockCount != lockId.LockCount)
                 {
                     return; // Something else locked it in the meantime.
                 }
                 transaction.Upsert(ToEntity(sessionItems));
                 transaction.Commit(_callSettings);
             }
     });
 }
 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);
     }
 }