private void EvictAboveSize(
            long desiredSize,
            EvictionReason reason)
        {
            ICollection <IEntry> entries;

            try
            {
                entries = GetSortedEntries(_storage.GetEntries());
            }
            catch (IOException ioe)
            {
                _cacheErrorLogger.LogError(
                    CacheErrorCategory.EVICTION,
                    typeof(DiskStorageCache),
                    "evictAboveSize: " + ioe.Message);

                throw;
            }

            long cacheSizeBeforeClearance = _cacheStats.Size;
            long deleteSize   = cacheSizeBeforeClearance - desiredSize;
            int  itemCount    = 0;
            long sumItemSizes = 0L;

            foreach (var entry in entries)
            {
                if (sumItemSizes > (deleteSize))
                {
                    break;
                }

                long deletedSize = _storage.Remove(entry);
                _resourceIndex.Remove(entry.Id);
                if (deletedSize > 0)
                {
                    itemCount++;
                    sumItemSizes += deletedSize;
                    SettableCacheEvent cacheEvent = SettableCacheEvent.Obtain()
                                                    .SetResourceId(entry.Id)
                                                    .SetEvictionReason(reason)
                                                    .SetItemSize(deletedSize)
                                                    .SetCacheSize(cacheSizeBeforeClearance - sumItemSizes)
                                                    .SetCacheLimit(desiredSize);
                    _cacheEventListener.OnEviction(cacheEvent);
                    cacheEvent.Recycle();
                }
            }

            _cacheStats.Increment(-sumItemSizes, -itemCount);
            _storage.PurgeUnexpectedResources();
        }
        /// <summary>
        /// Obtains the cache event instance.
        /// </summary>
        public static SettableCacheEvent Obtain()
        {
            lock (RECYCLER_LOCK)
            {
                if (_firstRecycledEvent != null)
                {
                    SettableCacheEvent eventToReuse = _firstRecycledEvent;
                    _firstRecycledEvent             = eventToReuse._nextRecycledEvent;
                    eventToReuse._nextRecycledEvent = null;
                    _recycledCount--;
                    return(eventToReuse);
                }
            }

            return(new SettableCacheEvent());
        }
        /// <summary>
        /// Recycles the cache event.
        /// </summary>
        public void Recycle()
        {
            lock (RECYCLER_LOCK)
            {
                if (_recycledCount < MAX_RECYCLED)
                {
                    Reset();
                    _recycledCount++;

                    if (_firstRecycledEvent != null)
                    {
                        _nextRecycledEvent = _firstRecycledEvent;
                    }

                    _firstRecycledEvent = this;
                }
            }
        }