예제 #1
0
        /// <summary>
        /// Insert an item into the cache with the specified time to live,
        /// sliding expiration and priority.
        /// </summary>
        /// <param name="keyName">The cache key</param>
        /// <param name="value">The cache value</param>
        /// <param name="timeToLive">How long in seconds the object should be cached.</param>
        /// <param name="slidingExpiration">Whether or not to reset the time to live if the object is touched.</param>
        /// <param name="priority">Priority of the cache entry.</param>
        public void Insert(object keyName, object value, int timeToLive, bool slidingExpiration, CacheItemPriority priority)
        {
            TimeSpan timeToLiveAsTimeSpan = TimeSpan.FromSeconds(timeToLive);

            Guard.IsNotNull(keyName, "key");
            Guard.IsTrue(TimeSpan.Zero <= timeToLiveAsTimeSpan, "timeToLive");
            System.Web.Caching.CacheItemPriority aspNetPriority = ConvertToAspNetPriority(priority);

            string key = BuildKey(keyName);

            if (TimeSpan.Zero < timeToLiveAsTimeSpan)
            {
                if (slidingExpiration)
                {
                    _cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, timeToLiveAsTimeSpan, aspNetPriority, null);
                }
                else
                {
                    DateTime absoluteExpiration = DateTime.Now.AddSeconds(timeToLive);
                    _cache.Insert(key, value, null, absoluteExpiration, Cache.NoSlidingExpiration, aspNetPriority, null);
                }
            }
            else
            {
                _cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, aspNetPriority, null);
            }
        }
예제 #2
0
        public object GetCacheItem(
            string cacheKey,
            Func <object> getCacheItem,
            TimeSpan?timeout,
            bool isSliding             = false,
            CacheItemPriority priority = CacheItemPriority.Normal,
            CacheItemRemovedCallback removedCallback = null,
            string[] dependentFiles = null)
        {
            using (var lck = new UpgradeableReadLock(Locker))
            {
                var result = MemoryCache.Get(cacheKey);
                if (result == null)
                {
                    lck.UpgradeToWriteLock();

                    result = getCacheItem();
                    if (result != null)
                    {
                        var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
                        MemoryCache.Set(cacheKey, result, policy);
                    }
                }
                return(result);
            }
        }
예제 #3
0
        /// <summary>
        /// 添加一个缓存对象(键值不能重复)
        /// </summary>
        /// <param name="key">缓存项键</param>
        /// <param name="value">缓存项值</param>
        /// <param name="absoluteExpiration">绝对到期时间 如果指定此时间 则slidingExpiration必须是TimeSpan.Zero</param>
        /// <param name="slidingExpiration">最后一次访问所插入对象时与该对象到期时之间的时间间隔(单位分钟)(现在时间与最后一次访问缓存对象的时间间隔超过指定间隔 则缓存对象过过期) 如果指定此间隔 则absoluteExpiration必须是DateTime.MaxValue</param>
        /// <param name="priority">优先级</param>
        /// <param name="onRemoveCallback">移除缓存项时通知应用程序的回调方法</param>
        public override void Add(string key, object value, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, Action <string, object, CacheItemRemovedReason> onRemoveCallback)
        {
            Guard.IsNotNull(key, "键不能为空");

            if (Contains(key))
            {
                throw new ArgumentNullException("key", "键已经存在");
            }

            CacheItemRemovedCallback removeCallback = (s, o, c) =>
            {
                if (onRemoveCallback != null)
                {
                    onRemoveCallback(s, o, c);
                }
            };

            System.Web.Caching.CacheItemPriority aspNetPriority = ConvertToAspNetPriority(priority);


            cache.Insert(key, value, null, absoluteExpiration, slidingExpiration, aspNetPriority, removeCallback);
        }
예제 #4
0
        public void Insert(object keyName, object value, int timeToLive, bool slidingExpiration, CacheItemPriority priority)
        {
            TimeSpan timeSpan = TimeSpan.FromSeconds((double)timeToLive);

            Guard.IsNotNull(keyName, "key");
            Guard.IsTrue(TimeSpan.Zero <= timeSpan, "timeToLive");
            System.Web.Caching.CacheItemPriority priority2 = this.ConvertToAspNetPriority(priority);
            string key = this.BuildKey(keyName);

            if (!(TimeSpan.Zero < timeSpan))
            {
                this._cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, priority2, null);
                return;
            }
            if (slidingExpiration)
            {
                this._cache.Insert(key, value, null, Cache.NoAbsoluteExpiration, timeSpan, priority2, null);
                return;
            }
            DateTime absoluteExpiration = DateTime.Now.AddSeconds((double)timeToLive);

            this._cache.Insert(key, value, null, absoluteExpiration, Cache.NoSlidingExpiration, priority2, null);
        }
예제 #5
0
        public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            object result = getCacheItem();

            if (result != null)
            {
                var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
                MemoryCache.Set(cacheKey, result, policy);
            }
        }
예제 #6
0
 private static void BaseInsert(string key, object value, CacheDependency dep, DateTime absoluteExpiration, TimeSpan slidingExpiration, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
 {
     if (value != null)
     {
         _cache.Insert(key, value, dep, absoluteExpiration, slidingExpiration, priority, onRemoveCallback);
     }
 }
예제 #7
0
 /// <summary>
 /// 插入缓存 使用文件依赖与过期时间,另可设置缓存优先级与缓存失效回调函数
 /// </summary>
 /// <param name="key"></param>
 /// <param name="obj"></param>
 /// <param name="absoluteExprition"></param>
 /// <param name="dep"></param>
 /// <param name="priority"></param>
 /// <param name="onRemoveCallback"></param>
 public static void Insert(string key, object obj, TimeSpan absoluteExprition, CacheDependency dep, System.Web.Caching.CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
 {
     if (obj != null)
     {
         BaseInsert(key, obj, dep, DateTime.Now.Add(absoluteExprition), System.Web.Caching.Cache.NoSlidingExpiration, priority, onRemoveCallback);
     }
 }
예제 #8
0
        public object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            // see notes in HttpRuntimeCacheProvider

            Lazy <object> result;

            using (var lck = new UpgradeableReadLock(_locker))
            {
                result = MemoryCache.Get(cacheKey) as Lazy <object>;
                if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result = new Lazy <object>(getCacheItem);
                    var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);

                    lck.UpgradeToWriteLock();
                    MemoryCache.Set(cacheKey, result, policy);
                }
            }

            return(result.Value);
        }
예제 #9
0
        /// <summary>
        /// Only call with already munged (KeyInContext style) keys.
        /// </summary>
        private void RawSet(string cacheKey, object value, int?durationSecs, bool isSliding, System.Web.Caching.CacheItemPriority priority)
        {
            LocalCache.OnLogDuration(cacheKey, durationSecs, "RawSet");
            var absolute = !isSliding && durationSecs.HasValue ? DateTime.UtcNow.AddSeconds(durationSecs.Value) : Cache.NoAbsoluteExpiration;
            var sliding  = isSliding && durationSecs.HasValue ? TimeSpan.FromSeconds(durationSecs.Value) : Cache.NoSlidingExpiration;

            HttpRuntime.Cache.Insert(cacheKey, value, null, absolute, sliding, priority, Removed);
            var evt = Added;

            if (evt != null)
            {
                evt(cacheKey, value, absolute, sliding, priority, durationSecs, isSliding);
            }
        }
        /// <summary>
        /// This overload is here for legacy purposes
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="getCacheItem"></param>
        /// <param name="timeout"></param>
        /// <param name="isSliding"></param>
        /// <param name="priority"></param>
        /// <param name="removedCallback"></param>
        /// <param name="dependency"></param>
        internal void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
        {
            // NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
            // and make sure we don't store a null value.

            var result = GetSafeLazy(getCacheItem);
            var value  = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache

            if (value == null)
            {
                return;                // do not store null values (backward compat)
            }
            cacheKey = GetCacheKey(cacheKey);

            var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
            var sliding  = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);

            try
            {
                _locker.EnterWriteLock();
                //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
                _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
            }
            finally
            {
                if (_locker.IsWriteLockHeld)
                {
                    _locker.ExitWriteLock();
                }
            }
        }
        /// <summary>
        /// This overload is here for legacy purposes
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="getCacheItem"></param>
        /// <param name="timeout"></param>
        /// <param name="isSliding"></param>
        /// <param name="priority"></param>
        /// <param name="removedCallback"></param>
        /// <param name="dependency"></param>
        /// <returns></returns>
        internal object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
        {
            cacheKey = GetCacheKey(cacheKey);

            // NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang,
            // getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and
            // nasty performance issues.

            // So.... we insert a Lazy<object> in the cache while holding the global application lock, and then rely
            // on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global
            // application lock has been released.

            // NOTE
            //   The Lazy value creation may produce a null value.
            //   Must make sure (for backward compatibility) that we pretend they are not in the cache.
            //   So if we find an entry in the cache that already has its value created and is null,
            //   pretend it was not there. If value is not already created, wait... and return null, that's
            //   what prior code did.

            // NOTE
            //   The Lazy value creation may throw.

            // So... the null value _will_ be in the cache but never returned

            Lazy <object> result;

            // Fast!
            // Only one thread can enter an UpgradeableReadLock at a time, but it does not prevent other
            // threads to enter a ReadLock in the meantime -- only upgrading to WriteLock will prevent all
            // reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
            // having to re-lock in case there's no value. Would need to benchmark to figure out whether
            // it's worth it, though...
            try
            {
                _locker.EnterReadLock();
                result = _cache.Get(cacheKey) as Lazy <object>; // null if key not found
            }
            finally
            {
                if (_locker.IsReadLockHeld)
                {
                    _locker.ExitReadLock();
                }
            }
            var value = result == null ? null : GetSafeLazyValue(result);

            if (value != null)
            {
                return(value);
            }

            using (var lck = new UpgradeableReadLock(_locker))
            {
                result = _cache.Get(cacheKey) as Lazy <object>; // null if key not found

                // cannot create value within the lock, so if result.IsValueCreated is false, just
                // do nothing here - means that if creation throws, a race condition could cause
                // more than one thread to reach the return statement below and throw - accepted.

                if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result = GetSafeLazy(getCacheItem);
                    var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
                    var sliding  = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);

                    lck.UpgradeToWriteLock();
                    //NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
                    _cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
                }
            }

            // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
            // exceptions (but try again and again) and silently eat them - however at
            // some point we have to report them - so need to re-throw here

            // this does not throw anymore
            //return result.Value;

            value = result.Value; // will not throw (safe lazy)
            if (value is ExceptionHolder eh)
            {
                eh.Exception.Throw();                              // throw once!
            }
            return(value);
        }
예제 #12
0
 public void Insert(string keyString, object value, int cacheDurationInSeconds, System.Web.Caching.CacheItemPriority priority)
 {
 }
예제 #13
0
        /// <inheritdoc />
        public object Get(string key, Func <object> factory, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            // see notes in HttpRuntimeAppCache

            Lazy <object> result;

            try
            {
                _locker.EnterUpgradeableReadLock();

                result = MemoryCache.Get(key) as Lazy <object>;
                if (result == null || FastDictionaryAppCacheBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result = FastDictionaryAppCacheBase.GetSafeLazy(factory);
                    var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);

                    try
                    {
                        _locker.EnterWriteLock();
                        //NOTE: This does an add or update
                        MemoryCache.Set(key, result, policy);
                    }
                    finally
                    {
                        if (_locker.IsWriteLockHeld)
                        {
                            _locker.ExitWriteLock();
                        }
                    }
                }
            }
            finally
            {
                if (_locker.IsUpgradeableReadLockHeld)
                {
                    _locker.ExitUpgradeableReadLock();
                }
            }

            //return result.Value;

            var value = result.Value; // will not throw (safe lazy)

            if (value is FastDictionaryAppCacheBase.ExceptionHolder eh)
            {
                eh.Exception.Throw();                                                         // throw once!
            }
            return(value);
        }
예제 #14
0
        ///// <summary>
        ///// Добавляет данные в кэш
        ///// </summary>
        ///// <param name="key">Название ключа кэша</param>
        ///// <param name="data">Данные, которые надо положить в кэш</param>
        ///// <param name="cacheDuration">Длительность хранения</param>
        ///// <param name="priority">Приоритет кэша</param>
        ///// <param name="onRemoved">Событие при удалении данных из кэша</param>
        //public static void AddCacheData(string key, object data, uint cacheDuration, CacheItemPriority priority, CacheItemRemovedCallback onRemoved)
        //{
        //    AddCacheData(key, data, null, cacheDuration, 0, priority, onRemoved);
        //}

        /// <summary>
        /// Вставка объекта в объект Cache с политиками сроков действия и приоритетов, а также с делегатом,
        /// которого можно использовать для уведомления приложения при удалении вставленного элемента из Cache.
        /// </summary>
        /// <param name="key">Ключ кэша, используемый для ссылки на объект.</param>
        /// <param name="data">Объект для вставки в кэш.</param>
        /// <param name="dependency">Переменная зависимостей кэша</param>
        /// <param name="cacheDuration">Время по истечению которого объект будет удален из кэша</param>
        /// <param name="slidingExpiration">Интервал в секундах между временем последнего обращения к вставленному объекту и временем истечения срока действия этого объекта.
        /// Если это значение равно 20 минутам, срок действия объекта истечет, и он будет удален из кэша через 20 минут после последнего обращения к этому объекту.
        /// Если используется скользящий срок действия, параметр cacheDuration должен быть равен 0.</param>
        /// <param name="priority">Цена объекта относительно других элементов, сохраненных в кэше, выраженная перечислением CacheItemPriority.
        /// Это значение используется в кэше при исключении объектов. Объекты с более низкой ценой удаляются из кэша раньше, чем объекты с более высокой ценой.</param>
        /// <param name="onRemoved">Цена объекта относительно других элементов, сохраненных в кэше, выраженная перечислением CacheItemPriority.
        /// Это значение используется в кэше при исключении объектов. Объекты с более низкой ценой удаляются из кэша раньше, чем объекты с более высокой ценой.</param>
        /// <param name="isTagMode">Добавлять ли данные в кэш как Insert или как Add (http://habrahabr.ru/post/61617/)</param>
        public static void AddCacheData(string key, object data, CacheDependency dependency, uint cacheDuration, uint slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoved, bool isTagMode = false)
        {
            if (Globals.Settings.Cache.Enabled)
            {
                switch (Globals.CacheMode)
                {
                case StorageModes.AspNet:
                    if (!isTagMode)
                    {
                        //перезаписывваем значение в любом случае
                        Cache.Insert(key, data, dependency,
                                     (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration,
                                     slidingExpiration > 0 ? new TimeSpan(0, 0, (int)cacheDuration) : Cache.NoSlidingExpiration, priority, onRemoved);
                    }
                    else
                    {
                        Cache.Add(key, data, dependency,
                                  (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration,
                                  slidingExpiration > 0 ? new TimeSpan(0, 0, (int)cacheDuration) : Cache.NoSlidingExpiration, priority, onRemoved);
                    }
                    break;

                case StorageModes.Redis:
                    if (onRemoved == null)
                    {
                        onRemoved = OnRemovedRedisCacheValue;
                    }
                    InsertCacheIntoRedisDb(key, data, cacheDuration);
                    if (!isTagMode)
                    {
                        Cache.Insert(key, false, dependency,
                                     (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration,
                                     slidingExpiration > 0 ? new TimeSpan(0, 0, (int)slidingExpiration) : Cache.NoSlidingExpiration, priority, onRemoved);
                    }
                    else
                    {
                        Cache.Add(key, false, dependency,
                                  (cacheDuration > 0 && slidingExpiration == 0) ? DateTime.Now.AddSeconds(cacheDuration) : Cache.NoAbsoluteExpiration,
                                  slidingExpiration > 0 ? new TimeSpan(0, 0, (int)slidingExpiration) : Cache.NoSlidingExpiration, priority, onRemoved);
                    }
                    break;

                case StorageModes.Memory:
                    if (!MemCache.ContainsKey(key))
                    {
                        MemCache.Add(key, data);
                    }
                    else
                    {
                        MemCache[key] = data;
                    }
                    break;
                }
            }
        }
        public object GetCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            // see notes in HttpRuntimeCacheProvider

            Lazy <object> result;

            using (var lck = new UpgradeableReadLock(_locker))
            {
                result = MemoryCache.Get(cacheKey) as Lazy <object>;
                if (result == null || DictionaryCacheProviderBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
                    var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);

                    lck.UpgradeToWriteLock();
                    //NOTE: This does an add or update
                    MemoryCache.Set(cacheKey, result, policy);
                }
            }

            //return result.Value;

            var value = result.Value; // will not throw (safe lazy)
            var eh    = value as DictionaryCacheProviderBase.ExceptionHolder;

            if (eh != null)
            {
                throw eh.Exception;             // throw once!
            }
            return(value);
        }
        public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            CacheDependency dependency = null;

            if (dependentFiles != null && dependentFiles.Any())
            {
                dependency = new CacheDependency(dependentFiles);
            }
            InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
        }
        public void InsertCacheItem(string cacheKey, Func <object> getCacheItem, TimeSpan?timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
        {
            // NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
            // and make sure we don't store a null value.

            var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
            var value  = result.Value; // force evaluation now

            if (value == null)
            {
                return;                // do not store null values (backward compat)
            }
            var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);

            //NOTE: This does an add or update
            MemoryCache.Set(cacheKey, result, policy);
        }
예제 #18
0
        /// <summary>
        /// Non-standard set for when we want to be absolutely explicit about cache priorities
        /// </summary>
        public void SetWithPriority <T>(string key, T value, int?durationSecs, bool isSliding, System.Web.Caching.CacheItemPriority priority)
        {
            LocalCache.OnLogDuration(key, durationSecs, "LocalCache.SetWithPriority");
            key = KeyInContext(key);

            RawSet(key, value, durationSecs, isSliding, priority);
        }