Example #1
0
        private void RemoveCacheEntryNoLock(MemoryCacheEntry cacheEntry)
        {
            ExpiresEntryRef entryRef = cacheEntry.ExpiresEntryRef;

            if (cacheEntry.ExpiresBucket != _bucket || entryRef.IsInvalid)
            {
                return;
            }

            ExpiresEntry[] entries    = (_pages[(entryRef.PageIndex)]._entries);
            int            entryIndex = entryRef.Index;

            RemoveCount(entries[entryIndex]._utcExpires);

            cacheEntry.ExpiresBucket        = 0xff;
            cacheEntry.ExpiresEntryRef      = ExpiresEntryRef.INVALID;
            entries[entryIndex]._cacheEntry = null;

            AddExpiresEntryToFreeList(entryRef);

            if (_cEntriesInUse == 0)
            {
                ResetCounts(DateTime.UtcNow);
            }

            Reduce();

            Debug.WriteLine("CacheExpiresRemove",
                            "Removed item=" + cacheEntry.Key +
                            ",_bucket=" + _bucket +
                            ",ref=" + entryRef +
                            ",now=" + DateTime.Now.ToString("o", CultureInfo.InvariantCulture) +
                            ",expires=" + cacheEntry.UtcAbsExp.ToLocalTime());
        }
Example #2
0
 public void Dispose()
 {
     if (Interlocked.Exchange(ref this._disposed, 1) == 0)
     {
         this._expires.EnableExpirationTimer(false);
         ArrayList list = new ArrayList(this._entries.Count);
         lock (this._entriesLock)
         {
             foreach (DictionaryEntry entry in this._entries)
             {
                 MemoryCacheEntry entry2 = entry.Value as MemoryCacheEntry;
                 list.Add(entry2);
             }
             foreach (MemoryCacheEntry entry3 in list)
             {
                 MemoryCacheKey key = entry3;
                 entry3.State = EntryState.RemovingFromCache;
                 this._entries.Remove(key);
             }
         }
         foreach (MemoryCacheEntry entry4 in list)
         {
             this.RemoveFromCache(entry4, CacheEntryRemovedReason.CacheSpecificEviction, false);
         }
         this._insertBlock.Close();
     }
 }
Example #3
0
        internal MemoryCacheEntry Remove(MemoryCacheKey key, MemoryCacheEntry entryToRemove, CacheEntryRemovedReason reason)
        {
            MemoryCacheEntry objA = null;

            lock (this._entriesLock)
            {
                if (this._disposed == 0)
                {
                    objA = this._entries[key] as MemoryCacheEntry;
                    if ((entryToRemove == null) || object.ReferenceEquals(objA, entryToRemove))
                    {
                        if (objA != null)
                        {
                            objA.State = EntryState.RemovingFromCache;
                        }
                        this._entries.Remove(key);
                    }
                    else
                    {
                        objA = null;
                    }
                }
            }
            this.RemoveFromCache(objA, reason, false);
            return(objA);
        }
Example #4
0
        internal void UtcUpdate(MemoryCacheEntry cacheEntry, DateTime utcNewExpires)
        {
            int oldBucket = cacheEntry.ExpiresBucket;
            int newBucket = UtcCalcExpiresBucket(utcNewExpires);

            if (oldBucket != newBucket)
            {
                Dbg.Trace("CacheExpiresUpdate",
                          "Updating item " + cacheEntry.Key + " from bucket " + oldBucket + " to new bucket " + newBucket);

                if (oldBucket != 0xff)
                {
                    _buckets[oldBucket].RemoveCacheEntry(cacheEntry);
                    cacheEntry.UtcAbsExp = utcNewExpires;
                    _buckets[newBucket].AddCacheEntry(cacheEntry);
                }
            }
            else
            {
                if (oldBucket != 0xff)
                {
                    _buckets[oldBucket].UtcUpdateCacheEntry(cacheEntry, utcNewExpires);
                }
            }
        }
        // 'updatePerfCounters' defaults to true since this method is called by all Get() operations
        // to update both the performance counters and the sliding expiration. Callers that perform
        // nested sliding expiration updates (like a MemoryCacheEntry touching its update sentinel)
        // can pass false to prevent these from unintentionally showing up in the perf counters.
        internal void UpdateExpAndUsage(MemoryCacheEntry entry, bool updatePerfCounters = true)
        {
            if (entry != null)
            {
                if (entry.InUsage() || entry.SlidingExp > TimeSpan.Zero)
                {
                    DateTime utcNow = DateTime.UtcNow;
                    entry.UpdateSlidingExp(utcNow, _expires);
                    entry.UpdateUsage(utcNow, _usage);
                }

                // DevDiv #67021: If this entry has an update sentinel, the sliding expiration is actually associated
                // with that sentinel, not with this entry. We need to update the sentinel's sliding expiration to
                // keep the sentinel from expiring, which in turn would force a removal of this entry from the cache.
                entry.UpdateSlidingExpForUpdateSentinel();

                if (updatePerfCounters && _perfCounters != null)
                {
                    _perfCounters.Increment(PerfCounterName.Hits);
                    _perfCounters.Increment(PerfCounterName.HitRatio);
                    _perfCounters.Increment(PerfCounterName.HitRatioBase);
                }
            }
            else
            {
                if (updatePerfCounters && _perfCounters != null)
                {
                    _perfCounters.Increment(PerfCounterName.Misses);
                    _perfCounters.Increment(PerfCounterName.HitRatioBase);
                }
            }
        }
Example #6
0
        internal void UtcUpdateCacheEntry(MemoryCacheEntry cacheEntry, DateTime utcExpires)
        {
            lock (this)
            {
                ExpiresEntryRef entryRef = cacheEntry.ExpiresEntryRef;
                if (cacheEntry.ExpiresBucket != _bucket || entryRef.IsInvalid)
                {
                    return;
                }

                ExpiresEntry[] entries    = (_pages[(entryRef.PageIndex)]._entries);
                int            entryIndex = entryRef.Index;

                Dbg.Assert(cacheEntry == entries[entryIndex]._cacheEntry);

                RemoveCount(entries[entryIndex]._utcExpires);
                AddCount(utcExpires);

                entries[entryIndex]._utcExpires = utcExpires;

                cacheEntry.UtcAbsExp = utcExpires;

                Dbg.Validate("CacheValidateExpires", this);
                Dbg.Trace("CacheExpiresUpdate", "Updated item " + cacheEntry.Key + " in bucket " + _bucket);
            }
        }
Example #7
0
        internal MemoryCacheEntry RemoveEntry(string key, MemoryCacheEntry entry, CacheEntryRemovedReason reason)
        {
            MemoryCacheKey   cacheKey = new MemoryCacheKey(key);
            MemoryCacheStore store    = GetStore(cacheKey);

            return(store.Remove(cacheKey, entry, reason));
        }
        private void RemoveFromCache(MemoryCacheEntry entry, CacheEntryRemovedReason reason, bool delayRelease = false)
        {
            // release outside of lock
            if (entry != null)
            {
                if (entry.InExpires())
                {
                    _expires.Remove(entry);
                }

                if (entry.InUsage())
                {
                    _usage.Remove(entry);
                }

                Dbg.Assert(entry.State == EntryState.RemovingFromCache, "entry.State = EntryState.RemovingFromCache");

                entry.State = EntryState.RemovedFromCache;
                if (!delayRelease)
                {
                    entry.Release(_cache, reason);
                }
                if (_perfCounters != null)
                {
                    _perfCounters.Decrement(PerfCounterName.Entries);
                    _perfCounters.Increment(PerfCounterName.Turnover);
                }
            }
        }
Example #9
0
        internal void Add(MemoryCacheEntry cacheEntry)
        {
            byte bucket = cacheEntry.UsageBucket;

            Debug.Assert(bucket != 0xff, "bucket != 0xff");
            _buckets[bucket].AddCacheEntry(cacheEntry);
        }
        public MemoryCacheEntry Dequeue()
        {
            MemoryCacheEntry ret = null;

            MemoryCacheEntry[] heap;
            bool locked = false;
            int  index;

            try {
                queueLock.EnterWriteLock();
                locked = true;
                heap   = GetHeapWithShrink();
                if (heap == null || heapCount == 0)
                {
                    return(null);
                }

                ret          = heap [0];
                index        = checked (--heapCount);
                heap [0]     = heap [index];
                heap [index] = null;

                if (heapCount > 0)
                {
                    BubbleDown(heap);
                }

                return(ret);
            } finally {
                if (locked)
                {
                    queueLock.ExitWriteLock();
                }
            }
        }
 internal void AddCacheEntry(MemoryCacheEntry cacheEntry)
 {
     lock (this)
     {
         if (((byte)(cacheEntry.State & (EntryState.AddedToCache | EntryState.AddingToCache))) != 0)
         {
             ExpiresEntryRef expiresEntryRef = cacheEntry.ExpiresEntryRef;
             if ((cacheEntry.ExpiresBucket == 0xff) && expiresEntryRef.IsInvalid)
             {
                 if (this._freeEntryList._head == -1)
                 {
                     this.Expand();
                 }
                 ExpiresEntryRef freeExpiresEntry = this.GetFreeExpiresEntry();
                 cacheEntry.ExpiresBucket   = this._bucket;
                 cacheEntry.ExpiresEntryRef = freeExpiresEntry;
                 ExpiresEntry[] entryArray = this._pages[freeExpiresEntry.PageIndex]._entries;
                 int            index      = freeExpiresEntry.Index;
                 entryArray[index]._cacheEntry = cacheEntry;
                 entryArray[index]._utcExpires = cacheEntry.UtcAbsExp;
                 this.AddCount(cacheEntry.UtcAbsExp);
                 this._cEntriesInUse++;
                 if (((byte)(cacheEntry.State & (EntryState.AddedToCache | EntryState.AddingToCache))) == 0)
                 {
                     this.RemoveCacheEntryNoLock(cacheEntry);
                 }
             }
         }
     }
 }
Example #12
0
        internal void RemoveCacheEntry(MemoryCacheEntry cacheEntry)
        {
            lock (this)
            {
                UsageEntryRef entryRef = cacheEntry.UsageEntryRef;
                if (entryRef.IsInvalid)
                {
                    return;
                }

                UsageEntry[] entries    = (_pages[(entryRef.PageIndex)]._entries);
                int          entryIndex = entryRef.Ref1Index;

                cacheEntry.UsageEntryRef        = UsageEntryRef.INVALID;
                entries[entryIndex]._cacheEntry = null;

                RemoveEntryFromLastRefList(entryRef);

                AddUsageEntryToFreeList(entryRef);

                Reduce();

                Dbg.Trace("CacheUsageRemove",
                          "Removed item=" + cacheEntry.Key +
                          ",_bucket=" + _bucket +
                          ",ref=" + entryRef);
            }
        }
        internal MemoryCacheEntry Remove(MemoryCacheKey key, MemoryCacheEntry entryToRemove, CacheEntryRemovedReason reason)
        {
            MemoryCacheEntry entry = null;

            lock (_entriesLock) {
                if (_disposed == 0)
                {
                    // get current entry
                    entry = _entries[key] as MemoryCacheEntry;
                    // remove if it matches the entry to be removed (but always remove if entryToRemove is null)
                    if (entryToRemove == null || Object.ReferenceEquals(entry, entryToRemove))
                    {
                        // Dev10 865887: MemoryCache.Remove("\ue637\ud22a\u3e17") causes NullReferenceEx
                        if (entry != null)
                        {
                            entry.State = EntryState.RemovingFromCache;
                            _entries.Remove(key);
                        }
                    }
                    else
                    {
                        entry = null;
                    }
                }
            }
            // release outside of lock
            RemoveFromCache(entry, reason);
            return(entry);
        }
Example #14
0
        bool ExpireIfNeeded(string key, MemoryCacheEntry entry, bool needsLock = true, CacheEntryRemovedReason reason = CacheEntryRemovedReason.Expired)
        {
            bool locked = false;

            try {
                if (entry.IsExpired)
                {
                    if (needsLock)
                    {
                        cache_lock.EnterWriteLock();
                        locked = true;
                    }

                    cache.Remove(key);
                    perfCounters.Decrement(MemoryCachePerformanceCounters.CACHE_ENTRIES);
                    entry.Removed(owner, CacheEntryRemovedReason.Expired);

                    return(true);
                }
            } finally {
                if (locked)
                {
                    cache_lock.ExitWriteLock();
                }
            }

            return(false);
        }
        // private members

        private void AddToCache(MemoryCacheEntry entry)
        {
            // add outside of lock
            if (entry != null)
            {
                if (entry.HasExpiration())
                {
                    _expires.Add(entry);
                }

                if (entry.HasUsage() &&
                    (!entry.HasExpiration() || entry.UtcAbsExp - DateTime.UtcNow >= CacheUsage.MIN_LIFETIME_FOR_USAGE))
                {
                    _usage.Add(entry);
                }

                entry.State = EntryState.AddedToCache;
                entry.CallNotifyOnChanged();
                if (_perfCounters != null)
                {
                    _perfCounters.Increment(PerfCounterName.Entries);
                    _perfCounters.Increment(PerfCounterName.Turnover);
                }
            }
        }
Example #16
0
 internal void RemoveCacheEntry(MemoryCacheEntry cacheEntry)
 {
     lock (this)
     {
         RemoveCacheEntryNoLock(cacheEntry);
     }
 }
Example #17
0
        public void Enqueue(MemoryCacheEntry item)
        {
            if (item == null)
            {
                return;
            }

            bool locked = false;

            MemoryCacheEntry[] heap;

            try
            {
                queueLock.EnterWriteLock();
                locked             = true;
                heap               = GetHeapWithGrow();
                heap [heapCount++] = item;
                BubbleUp(heap);
            }
            finally
            {
                if (locked)
                {
                    queueLock.ExitWriteLock();
                }
            }
        }
Example #18
0
 // Associates this entry with an update sentinel. If this entry has a sliding expiration, we need to
 // touch the sentinel so that it doesn't expire.
 internal void ConfigureUpdateSentinel(MemoryCacheStore sentinelStore, MemoryCacheEntry sentinelEntry)
 {
     lock (this)
     {
         _fields ??= new SeldomUsedFields();
         _fields._updateSentinel = Tuple.Create(sentinelStore, sentinelEntry);
     }
 }
 internal void Update(MemoryCacheEntry cacheEntry)
 {
     byte usageBucket = cacheEntry.UsageBucket;
     if (usageBucket != 0xff)
     {
         this._buckets[usageBucket].UpdateCacheEntry(cacheEntry);
     }
 }
Example #20
0
        internal void Update(MemoryCacheEntry cacheEntry)
        {
            byte usageBucket = cacheEntry.UsageBucket;

            if (usageBucket != 0xff)
            {
                this._buckets[usageBucket].UpdateCacheEntry(cacheEntry);
            }
        }
Example #21
0
        internal void Remove(MemoryCacheEntry cacheEntry)
        {
            byte expiresBucket = cacheEntry.ExpiresBucket;

            if (expiresBucket != 0xff)
            {
                this._buckets[expiresBucket].RemoveCacheEntry(cacheEntry);
            }
        }
Example #22
0
        internal void Remove(MemoryCacheEntry cacheEntry)
        {
            byte bucket = cacheEntry.ExpiresBucket;

            if (bucket != 0xff)
            {
                _buckets[bucket].RemoveCacheEntry(cacheEntry);
            }
        }
Example #23
0
        internal void Update(MemoryCacheEntry cacheEntry)
        {
            byte bucket = cacheEntry.UsageBucket;

            if (bucket != 0xff)
            {
                _buckets[bucket].UpdateCacheEntry(cacheEntry);
            }
        }
Example #24
0
        private void InitDisposableMembers(MemoryCache cache)
        {
            bool flag = true;

            try
            {
                bool   hasChanged = false;
                string str        = null;
                this._dependencies = new List <MemoryCacheEntry>(this._keys.Count);
                if (this._keys.Count == 1)
                {
                    string           key        = this._keys[0];
                    MemoryCacheEntry entry      = cache.GetEntry(key);
                    DateTime         utcCreated = DATETIME_MINVALUE_UTC;
                    this.StartMonitoring(cache, entry, ref hasChanged, ref utcCreated);
                    str = key + utcCreated.Ticks.ToString("X", CultureInfo.InvariantCulture);
                    this._lastModified = utcCreated;
                }
                else
                {
                    int capacity = 0;
                    foreach (string str3 in this._keys)
                    {
                        capacity += str3.Length + 0x10;
                    }
                    StringBuilder builder = new StringBuilder(capacity);
                    foreach (string str4 in this._keys)
                    {
                        MemoryCacheEntry entry2 = cache.GetEntry(str4);
                        DateTime         time2  = DATETIME_MINVALUE_UTC;
                        this.StartMonitoring(cache, entry2, ref hasChanged, ref time2);
                        builder.Append(str4);
                        builder.Append(time2.Ticks.ToString("X", CultureInfo.InvariantCulture));
                        if (time2 > this._lastModified)
                        {
                            this._lastModified = time2;
                        }
                    }
                    str = builder.ToString();
                }
                this._uniqueId = str;
                if (hasChanged)
                {
                    base.OnChanged(null);
                }
                flag = false;
            }
            finally
            {
                base.InitializationComplete();
                if (flag)
                {
                    base.Dispose();
                }
            }
        }
        }                                           // hide default .ctor

        private void InitDisposableMembers(MemoryCache cache)
        {
            bool dispose = true;

            try
            {
                bool   hasChanged = false;
                string uniqueId   = null;
                _dependencies = new List <MemoryCacheEntry>(_keys.Count);
                if (_keys.Count == 1)
                {
                    string           k          = _keys[0];
                    MemoryCacheEntry entry      = cache.GetEntry(k);
                    DateTime         utcCreated = s_DATETIME_MINVALUE_UTC;
                    StartMonitoring(cache, entry, ref hasChanged, ref utcCreated);
                    uniqueId      = k + utcCreated.Ticks.ToString("X", CultureInfo.InvariantCulture);
                    _lastModified = utcCreated;
                }
                else
                {
                    int capacity = 0;
                    foreach (string key in _keys)
                    {
                        capacity += key.Length + MAX_CHAR_COUNT_OF_LONG_CONVERTED_TO_HEXADECIMAL_STRING;
                    }
                    StringBuilder sb = new StringBuilder(capacity);
                    foreach (string key in _keys)
                    {
                        MemoryCacheEntry entry      = cache.GetEntry(key);
                        DateTime         utcCreated = s_DATETIME_MINVALUE_UTC;
                        StartMonitoring(cache, entry, ref hasChanged, ref utcCreated);
                        sb.Append(key);
                        sb.Append(utcCreated.Ticks.ToString("X", CultureInfo.InvariantCulture));
                        if (utcCreated > _lastModified)
                        {
                            _lastModified = utcCreated;
                        }
                    }
                    uniqueId = sb.ToString();
                }
                _uniqueId = uniqueId;
                if (hasChanged)
                {
                    OnChanged(null);
                }
                dispose = false;
            }
            finally
            {
                InitializationComplete();
                if (dispose)
                {
                    Dispose();
                }
            }
        }
 internal void Add(MemoryCacheEntry cacheEntry)
 {
     DateTime utcNow = DateTime.UtcNow;
     if (utcNow > cacheEntry.UtcAbsExp)
     {
         cacheEntry.UtcAbsExp = utcNow;
     }
     int index = this.UtcCalcExpiresBucket(cacheEntry.UtcAbsExp);
     this._buckets[index].AddCacheEntry(cacheEntry);
 }
Example #27
0
        long DoRemoveExpiredItems(bool needLock)
        {
            long count  = 0;
            bool locked = false;

            try {
                if (needLock)
                {
                    cache_lock.EnterWriteLock();
                    locked = true;
                }

                if (timedItems == null)
                {
                    return(0);
                }

                long             now   = DateTime.Now.Ticks;
                MemoryCacheEntry entry = timedItems.Peek();

                while (entry != null)
                {
                    if (entry.Disabled)
                    {
                        timedItems.Dequeue();
                        entry = timedItems.Peek();
                        continue;
                    }

                    if (entry.ExpiresAt > now)
                    {
                        break;
                    }

                    timedItems.Dequeue();
                    count++;
                    DoRemoveEntry(entry, true, entry.Key, CacheEntryRemovedReason.Expired);
                    entry = timedItems.Peek();
                }

                if (entry == null)
                {
                    timedItems = null;
                    expirationTimer.Dispose();
                    expirationTimer = null;
                }

                return(count);
            } finally {
                if (locked)
                {
                    cache_lock.ExitWriteLock();
                }
            }
        }
Example #28
0
        internal void Remove(MemoryCacheEntry entry)
        {
            if (entry == null)
            {
                return;
            }

            string key = entry.Key;

            FindContainer(key).Remove(key);
        }
Example #29
0
        internal void Add(MemoryCacheEntry cacheEntry)
        {
            DateTime utcNow = DateTime.UtcNow;

            if (utcNow > cacheEntry.UtcAbsExp)
            {
                cacheEntry.UtcAbsExp = utcNow;
            }
            int index = this.UtcCalcExpiresBucket(cacheEntry.UtcAbsExp);

            this._buckets[index].AddCacheEntry(cacheEntry);
        }
Example #30
0
        internal MemoryCacheEntry Get(MemoryCacheKey key)
        {
            MemoryCacheEntry entryToRemove = this._entries[key] as MemoryCacheEntry;

            if ((entryToRemove != null) && (entryToRemove.UtcAbsExp <= DateTime.UtcNow))
            {
                this.Remove(key, entryToRemove, CacheEntryRemovedReason.Expired);
                entryToRemove = null;
            }
            this.UpdateExpAndUsage(entryToRemove);
            return(entryToRemove);
        }
Example #31
0
        public object AddOrGetExisting(string key, object value, CacheItemPolicy policy)
        {
            bool readLocked = false, writeLocked = false;

            try {
                cache_lock.EnterUpgradeableReadLock();
                readLocked = true;

                MemoryCacheEntry entry;
                if (cache.TryGetValue(key, out entry) && entry != null)
                {
                    perfCounters.Increment(MemoryCachePerformanceCounters.CACHE_HITS);
                    if (entry.IsSliding)
                    {
                        entry.UpdateSlidingExpiry();
                    }

                    return(entry.Value);
                }
                perfCounters.Increment(MemoryCachePerformanceCounters.CACHE_MISSES);

                cache_lock.EnterWriteLock();
                writeLocked = true;

                if (policy == null)
                {
                    entry = new MemoryCacheEntry(owner, key, value);
                }
                else
                {
                    entry = new MemoryCacheEntry(owner, key, value,
                                                 policy.AbsoluteExpiration,
                                                 policy.ChangeMonitors,
                                                 policy.Priority,
                                                 policy.RemovedCallback,
                                                 policy.SlidingExpiration,
                                                 policy.UpdateCallback);
                }

                AddToCache(key, entry);
                return(null);
            } finally {
                if (writeLocked)
                {
                    cache_lock.ExitWriteLock();
                }
                if (readLocked)
                {
                    cache_lock.ExitUpgradeableReadLock();
                }
            }
        }
Example #32
0
        internal void Add(MemoryCacheEntry cacheEntry)
        {
            DateTime utcNow = DateTime.UtcNow;

            if (utcNow > cacheEntry.UtcAbsExp)
            {
                cacheEntry.UtcAbsExp = utcNow;
            }

            int bucket = UtcCalcExpiresBucket(cacheEntry.UtcAbsExp);

            _buckets[bucket].AddCacheEntry(cacheEntry);
        }
Example #33
0
		public void Remove (MemoryCacheEntry entry)
		{
			if (entry == null)
				return;
			
			int hash = entry.GetHashCode ();
			LinkedListNode <MemoryCacheEntry> node;
			
			if (index.TryGetValue (hash, out node)) {
				lru.Remove (node);
				index.Remove (hash);
			}
		}
 private void StartMonitoring(MemoryCache cache, MemoryCacheEntry entry, ref bool hasChanged, ref DateTime utcCreated) {
     if (entry != null) {
         // pass reference to self so the dependency can notify us when it changes
         entry.AddDependent(cache, this);
         // add dependency to collection so we can dispose it later
         _dependencies.Add(entry);
         // has the entry already changed?
         if (entry.State != EntryState.AddedToCache) {
             hasChanged = true;
         }
         utcCreated = entry.UtcCreated;
     }
     else {
         // the entry does not exist--set hasChanged to true so the user is notified
         hasChanged = true;
     }
 }
Example #35
0
		public void Update (MemoryCacheEntry entry)
		{
			if (entry == null)
				return;

			int hash = entry.GetHashCode ();
			LinkedListNode <MemoryCacheEntry> node;
			
			if (!index.TryGetValue (hash, out node)) {
				node = new LinkedListNode <MemoryCacheEntry> (entry);
				index.Add (hash, node);
			} else {
				lru.Remove (node);
				node.Value = entry;
			}
			
			lru.AddLast (node);
		}
        // private members        

        private void AddToCache(MemoryCacheEntry entry) {
            // add outside of lock
            if (entry != null) {
                if (entry.HasExpiration()) {
                    _expires.Add(entry);
                }

                if (entry.HasUsage()
                    && (!entry.HasExpiration() || entry.UtcAbsExp - DateTime.UtcNow >= CacheUsage.MIN_LIFETIME_FOR_USAGE)) {
                    _usage.Add(entry);
                }

                entry.State = EntryState.AddedToCache;
                entry.CallNotifyOnChanged();
                if (_perfCounters != null) {
                    _perfCounters.Increment(PerfCounterName.Entries);
                    _perfCounters.Increment(PerfCounterName.Turnover);
                }
            }
        }
 internal MemoryCacheEntry AddOrGetExisting(MemoryCacheKey key, MemoryCacheEntry entry)
 {
     if (this._useInsertBlock && entry.HasUsage())
     {
         this.WaitInsertBlock();
     }
     MemoryCacheEntry entry2 = null;
     MemoryCacheEntry entry3 = null;
     bool flag = false;
     lock (this._entriesLock)
     {
         if (this._disposed == 0)
         {
             entry2 = this._entries[key] as MemoryCacheEntry;
             if ((entry2 != null) && (entry.UtcAbsExp <= DateTime.UtcNow))
             {
                 entry3 = entry2;
                 entry3.State = EntryState.RemovingFromCache;
                 entry2 = null;
             }
             if (entry2 == null)
             {
                 entry.State = EntryState.AddingToCache;
                 flag = true;
                 this._entries[key] = entry;
             }
         }
     }
     bool delayRelease = true;
     this.RemoveFromCache(entry3, CacheEntryRemovedReason.Expired, delayRelease);
     if (flag)
     {
         this.AddToCache(entry);
     }
     this.UpdateExpAndUsage(entry2);
     if (entry3 != null)
     {
         entry3.Release(this._cache, CacheEntryRemovedReason.Expired);
     }
     return entry2;
 }
        private void RemoveFromCache(MemoryCacheEntry entry, CacheEntryRemovedReason reason, bool delayRelease = false) {
            // release outside of lock
            if (entry != null) {
                if (entry.InExpires()) {
                    _expires.Remove(entry);
                }

                if (entry.InUsage()) {
                    _usage.Remove(entry);
                }

                Dbg.Assert(entry.State == EntryState.RemovingFromCache, "entry.State = EntryState.RemovingFromCache");

                entry.State = EntryState.RemovedFromCache;
                if (!delayRelease) {
                    entry.Release(_cache, reason);
                }
                if (_perfCounters != null) {
                    _perfCounters.Decrement(PerfCounterName.Entries);
                    _perfCounters.Increment(PerfCounterName.Turnover);
                }
            }
        }
Example #39
0
		bool ExpireIfNeeded (string key, MemoryCacheEntry entry, bool needsLock = true, CacheEntryRemovedReason reason = CacheEntryRemovedReason.Expired)
		{
			bool locked = false;
			
			try {
				if (entry.IsExpired) {
					if (needsLock) {
						cache_lock.EnterWriteLock ();
						locked = true;
					}
					
					cache.Remove (key);
					perfCounters.Decrement (MemoryCachePerformanceCounters.CACHE_ENTRIES);
					entry.Removed (owner, CacheEntryRemovedReason.Expired);
					
					return true;
				}
			} finally {
				if (locked)
					cache_lock.ExitWriteLock ();
			}
			
			return false;
		}
Example #40
0
		// NOTE: this method _MUST_ be called with the write lock held
		void AddToCache (string key, MemoryCacheEntry entry, bool update = false)
		{
			if (update)
				cache [key] = entry;
			else
				cache.Add (key, entry);
			lru.Update (entry);
			entry.Added ();
			if (!update)
				perfCounters.Increment (MemoryCachePerformanceCounters.CACHE_ENTRIES);
			
			if (entry.IsExpirable)
				UpdateExpirable (entry);
		}
		void BubbleDown (MemoryCacheEntry[] heap)
		{
			int index = 0;
			int left = 1;
			int right = 2;
			MemoryCacheEntry item = heap [0];
			int selected = (right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt) ? 2 : 1;

			while (selected < heapCount && heap [selected].ExpiresAt < item.ExpiresAt) {
				heap [index] = heap [selected];
				index = selected;
				left = checked((index << 1) + 1);
				right = left + 1;
				selected = right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt ? right : left;
			}
			heap [index] = item;
		}
		void BubbleUp (MemoryCacheEntry[] heap)
		{
			int index, parentIndex;
			MemoryCacheEntry parent, item;
			
			if (heapCount <= 1)
				return;
			
			index = checked(heapCount - 1);
			parentIndex = checked((index - 1) >> 1);

			item = heap [index];
			while (index > 0) {
				parent = heap [parentIndex];
				if (heap [index].ExpiresAt >= parent.ExpiresAt)
					break;
				
				heap [index] = parent;
				index = parentIndex;
				parentIndex = (index - 1) >> 1;
			}

			heap [index] = item;
		}
		public void Enqueue (MemoryCacheEntry item)
		{
			if (item == null)
				return;

			bool locked = false;
			MemoryCacheEntry[] heap;
			
			try {
				queueLock.EnterWriteLock ();
				locked = true;
				heap = GetHeapWithGrow ();
				heap [checked(heapCount++)] = item;
				BubbleUp (heap);
			} finally {
				if (locked)
					queueLock.ExitWriteLock ();
			}
		}
 internal MemoryCacheEntry AddOrGetExisting(MemoryCacheKey key, MemoryCacheEntry entry) {
     if (_useInsertBlock && entry.HasUsage()) {
         WaitInsertBlock();
     }
     MemoryCacheEntry existingEntry = null;
     MemoryCacheEntry toBeReleasedEntry = null;
     bool added = false;
     lock (_entriesLock) {
         if (_disposed == 0) {
             existingEntry = _entries[key] as MemoryCacheEntry;
             // has it expired?
             if (existingEntry != null && existingEntry.UtcAbsExp <= DateTime.UtcNow) {
                 toBeReleasedEntry = existingEntry;
                 toBeReleasedEntry.State = EntryState.RemovingFromCache;
                 existingEntry = null;
             }
             // can we add entry to the cache?
             if (existingEntry == null) {
                 entry.State = EntryState.AddingToCache;
                 added = true;
                 _entries[key] = entry;
             }
         }
     }
     // release outside of lock
     RemoveFromCache(toBeReleasedEntry, CacheEntryRemovedReason.Expired, delayRelease:true);
     if (added) {
         // add outside of lock
         AddToCache(entry);
     }
     // update outside of lock
     UpdateExpAndUsage(existingEntry);
     
     // Dev10 861163: Call Release after the new entry has been completely added so 
     // that the CacheItemRemovedCallback can take a dependency on the newly inserted item.
     if (toBeReleasedEntry != null) {
         toBeReleasedEntry.Release(_cache, CacheEntryRemovedReason.Expired);
     }
     return existingEntry;
 }
 internal void UtcUpdate(MemoryCacheEntry cacheEntry, DateTime utcNewExpires)
 {
     int expiresBucket = cacheEntry.ExpiresBucket;
     int index = this.UtcCalcExpiresBucket(utcNewExpires);
     if (expiresBucket != index)
     {
         if (expiresBucket != 0xff)
         {
             this._buckets[expiresBucket].RemoveCacheEntry(cacheEntry);
             cacheEntry.UtcAbsExp = utcNewExpires;
             this._buckets[index].AddCacheEntry(cacheEntry);
         }
     }
     else if (expiresBucket != 0xff)
     {
         this._buckets[expiresBucket].UtcUpdateCacheEntry(cacheEntry, utcNewExpires);
     }
 }
Example #46
0
		// NOTE: this must be called with the write lock held
		void DoRemoveEntry (MemoryCacheEntry entry, bool updateLRU = true, string key = null, CacheEntryRemovedReason reason = CacheEntryRemovedReason.Removed)
		{
			if (key == null)
				key = entry.Key;

			cache.Remove (key);
			if (updateLRU)
				lru.Remove (entry);
			perfCounters.Decrement (MemoryCachePerformanceCounters.CACHE_ENTRIES);
			entry.Removed (owner, reason);
		}
 internal void AddCacheEntry(MemoryCacheEntry cacheEntry)
 {
     lock (this)
     {
         if (this._freeEntryList._head == -1)
         {
             this.Expand();
         }
         UsageEntryRef freeUsageEntry = this.GetFreeUsageEntry();
         UsageEntryRef ref3 = new UsageEntryRef(freeUsageEntry.PageIndex, -freeUsageEntry.Ref1Index);
         cacheEntry.UsageEntryRef = freeUsageEntry;
         UsageEntry[] entryArray = this._pages[freeUsageEntry.PageIndex]._entries;
         int index = freeUsageEntry.Ref1Index;
         entryArray[index]._cacheEntry = cacheEntry;
         entryArray[index]._utcDate = DateTime.UtcNow;
         entryArray[index]._ref1._prev = UsageEntryRef.INVALID;
         entryArray[index]._ref2._next = this._addRef2Head;
         if (this._lastRefHead.IsInvalid)
         {
             entryArray[index]._ref1._next = ref3;
             entryArray[index]._ref2._prev = freeUsageEntry;
             this._lastRefTail = ref3;
         }
         else
         {
             UsageEntryRef iNVALID;
             UsageEntryRef ref5;
             entryArray[index]._ref1._next = this._lastRefHead;
             if (this._lastRefHead.IsRef1)
             {
                 this._pages[this._lastRefHead.PageIndex]._entries[this._lastRefHead.Ref1Index]._ref1._prev = freeUsageEntry;
             }
             else if (this._lastRefHead.IsRef2)
             {
                 this._pages[this._lastRefHead.PageIndex]._entries[this._lastRefHead.Ref2Index]._ref2._prev = freeUsageEntry;
             }
             else
             {
                 this._lastRefTail = freeUsageEntry;
             }
             if (this._addRef2Head.IsInvalid)
             {
                 ref5 = this._lastRefTail;
                 iNVALID = UsageEntryRef.INVALID;
             }
             else
             {
                 ref5 = this._pages[this._addRef2Head.PageIndex]._entries[this._addRef2Head.Ref2Index]._ref2._prev;
                 iNVALID = this._addRef2Head;
             }
             entryArray[index]._ref2._prev = ref5;
             if (ref5.IsRef1)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref1Index]._ref1._next = ref3;
             }
             else if (ref5.IsRef2)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref2Index]._ref2._next = ref3;
             }
             else
             {
                 this._lastRefHead = ref3;
             }
             if (iNVALID.IsRef1)
             {
                 this._pages[iNVALID.PageIndex]._entries[iNVALID.Ref1Index]._ref1._prev = ref3;
             }
             else if (iNVALID.IsRef2)
             {
                 this._pages[iNVALID.PageIndex]._entries[iNVALID.Ref2Index]._ref2._prev = ref3;
             }
             else
             {
                 this._lastRefTail = ref3;
             }
         }
         this._lastRefHead = freeUsageEntry;
         this._addRef2Head = ref3;
         this._cEntriesInUse++;
     }
 }
 internal void UpdateCacheEntry(MemoryCacheEntry cacheEntry)
 {
     lock (this)
     {
         UsageEntryRef usageEntryRef = cacheEntry.UsageEntryRef;
         if (!usageEntryRef.IsInvalid)
         {
             UsageEntry[] entryArray = this._pages[usageEntryRef.PageIndex]._entries;
             int index = usageEntryRef.Ref1Index;
             UsageEntryRef ref3 = new UsageEntryRef(usageEntryRef.PageIndex, -usageEntryRef.Ref1Index);
             UsageEntryRef ref4 = entryArray[index]._ref2._prev;
             UsageEntryRef ref5 = entryArray[index]._ref2._next;
             if (ref4.IsRef1)
             {
                 this._pages[ref4.PageIndex]._entries[ref4.Ref1Index]._ref1._next = ref5;
             }
             else if (ref4.IsRef2)
             {
                 this._pages[ref4.PageIndex]._entries[ref4.Ref2Index]._ref2._next = ref5;
             }
             else
             {
                 this._lastRefHead = ref5;
             }
             if (ref5.IsRef1)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref1Index]._ref1._prev = ref4;
             }
             else if (ref5.IsRef2)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref2Index]._ref2._prev = ref4;
             }
             else
             {
                 this._lastRefTail = ref4;
             }
             if (this._addRef2Head == ref3)
             {
                 this._addRef2Head = ref5;
             }
             entryArray[index]._ref2 = entryArray[index]._ref1;
             ref4 = entryArray[index]._ref2._prev;
             ref5 = entryArray[index]._ref2._next;
             if (ref4.IsRef1)
             {
                 this._pages[ref4.PageIndex]._entries[ref4.Ref1Index]._ref1._next = ref3;
             }
             else if (ref4.IsRef2)
             {
                 this._pages[ref4.PageIndex]._entries[ref4.Ref2Index]._ref2._next = ref3;
             }
             else
             {
                 this._lastRefHead = ref3;
             }
             if (ref5.IsRef1)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref1Index]._ref1._prev = ref3;
             }
             else if (ref5.IsRef2)
             {
                 this._pages[ref5.PageIndex]._entries[ref5.Ref2Index]._ref2._prev = ref3;
             }
             else
             {
                 this._lastRefTail = ref3;
             }
             entryArray[index]._ref1._prev = UsageEntryRef.INVALID;
             entryArray[index]._ref1._next = this._lastRefHead;
             if (this._lastRefHead.IsRef1)
             {
                 this._pages[this._lastRefHead.PageIndex]._entries[this._lastRefHead.Ref1Index]._ref1._prev = usageEntryRef;
             }
             else if (this._lastRefHead.IsRef2)
             {
                 this._pages[this._lastRefHead.PageIndex]._entries[this._lastRefHead.Ref2Index]._ref2._prev = usageEntryRef;
             }
             else
             {
                 this._lastRefTail = usageEntryRef;
             }
             this._lastRefHead = usageEntryRef;
         }
     }
 }
 internal void RemoveCacheEntry(MemoryCacheEntry cacheEntry)
 {
     lock (this)
     {
         UsageEntryRef usageEntryRef = cacheEntry.UsageEntryRef;
         if (!usageEntryRef.IsInvalid)
         {
             UsageEntry[] entryArray = this._pages[usageEntryRef.PageIndex]._entries;
             int index = usageEntryRef.Ref1Index;
             cacheEntry.UsageEntryRef = UsageEntryRef.INVALID;
             entryArray[index]._cacheEntry = null;
             this.RemoveEntryFromLastRefList(usageEntryRef);
             this.AddUsageEntryToFreeList(usageEntryRef);
             this.Reduce();
         }
     }
 }
Example #50
0
 internal MemoryCacheEntry RemoveEntry(string key, MemoryCacheEntry entry, CacheEntryRemovedReason reason) {
     MemoryCacheKey cacheKey = new MemoryCacheKey(key);
     MemoryCacheStore store = GetStore(cacheKey);
     return store.Remove(cacheKey, entry, reason);
 }
 internal MemoryCacheEntry RemoveEntry(string key, MemoryCacheEntry entry, CacheEntryRemovedReason reason)
 {
     MemoryCacheKey key2 = new MemoryCacheKey(key);
     return this.GetStore(key2).Remove(key2, entry, reason);
 }
Example #52
0
        // DevDiv Bugs 162763: 
        // Add a an event that fires *before* an item is evicted from the ASP.NET Cache
        internal void Set(string key, 
                          object value,
                          Collection<ChangeMonitor> changeMonitors,
                          DateTimeOffset absoluteExpiration,
                          TimeSpan slidingExpiration,
                          CacheEntryUpdateCallback onUpdateCallback) {
            if (key == null) {
                throw new ArgumentNullException("key");
            }
            if (changeMonitors == null
                && absoluteExpiration == ObjectCache.InfiniteAbsoluteExpiration 
                && slidingExpiration == ObjectCache.NoSlidingExpiration) {
                throw new ArgumentException(R.Invalid_argument_combination);
            }
            if (onUpdateCallback == null) {
                throw new ArgumentNullException("onUpdateCallback");
            }
            if (IsDisposed) {
                if (changeMonitors != null) {
                    foreach (ChangeMonitor monitor in changeMonitors) {
                        if (monitor != null) {
                            monitor.Dispose();
                        }
                    }
                }
                return;
            }
            // Insert updatable cache entry
            MemoryCacheKey cacheKey = new MemoryCacheKey(key);
            MemoryCacheStore store = GetStore(cacheKey);
            MemoryCacheEntry cacheEntry = new MemoryCacheEntry(key, 
                                                               value, 
                                                               ObjectCache.InfiniteAbsoluteExpiration, 
                                                               ObjectCache.NoSlidingExpiration, 
                                                               CacheItemPriority.NotRemovable, 
                                                               null,
                                                               null, 
                                                               this);
            store.Set(cacheKey, cacheEntry);

            // Ensure the sentinel depends on its updatable entry
            string[] cacheKeys = { key };
            ChangeMonitor expensiveObjectDep = CreateCacheEntryChangeMonitor(cacheKeys);
            if (changeMonitors == null) {
                changeMonitors = new Collection<ChangeMonitor>();
            }
            changeMonitors.Add(expensiveObjectDep);

            // Insert sentinel entry for the updatable cache entry 
            MemoryCacheKey sentinelCacheKey = new MemoryCacheKey("OnUpdateSentinel" + key);
            MemoryCacheStore sentinelStore = GetStore(sentinelCacheKey);
            MemoryCacheEntry sentinelCacheEntry = new MemoryCacheEntry(sentinelCacheKey.Key,
                                                                       new SentinelEntry(key, expensiveObjectDep, onUpdateCallback),
                                                                       absoluteExpiration, 
                                                                       slidingExpiration,
                                                                       CacheItemPriority.NotRemovable, 
                                                                       changeMonitors,
                                                                       s_sentinelRemovedCallback, 
                                                                       this);
            sentinelStore.Set(sentinelCacheKey, sentinelCacheEntry);
            cacheEntry.ConfigureUpdateSentinel(sentinelStore, sentinelCacheEntry);
        }
Example #53
0
		// NOTE: this method _MUST_ be called with the write lock held
		void UpdateExpirable (MemoryCacheEntry entry)
		{
			if (timedItems == null)
				timedItems = new MemoryCacheEntryPriorityQueue ();

			timedItems.Enqueue (entry);

			if (expirationTimer == null)
				expirationTimer = new Timer (RemoveExpiredItems, null, owner.TimerPeriod, owner.TimerPeriod);
		}
        internal void Set(MemoryCacheKey key, MemoryCacheEntry entry) {
            if (_useInsertBlock && entry.HasUsage()) {
                WaitInsertBlock();
            }
            MemoryCacheEntry existingEntry = null;
            bool added = false;
            lock (_entriesLock) {
                if (_disposed == 0) {
                    existingEntry = _entries[key] as MemoryCacheEntry;
                    if (existingEntry != null) {
                        existingEntry.State = EntryState.RemovingFromCache;
                    }
                    entry.State = EntryState.AddingToCache;
                    added = true;
                    _entries[key] = entry;
                }
            }

            CacheEntryRemovedReason reason = CacheEntryRemovedReason.Removed;
            if (existingEntry != null) {
                if (existingEntry.UtcAbsExp <= DateTime.UtcNow) {
                    reason = CacheEntryRemovedReason.Expired;
                }
                RemoveFromCache(existingEntry, reason, delayRelease:true);
            }
            if (added) {
                AddToCache(entry);
            }
            // Dev10 861163: Call Release after the new entry has been completely added so 
            // that the CacheItemRemovedCallback can take a dependency on the newly inserted item.
            if (existingEntry != null) {
                existingEntry.Release(_cache, reason);
            }
        }
Example #55
0
		public object AddOrGetExisting (string key, object value, CacheItemPolicy policy)
		{
			bool readLocked = false, writeLocked = false;
			try {
				cache_lock.EnterUpgradeableReadLock ();
				readLocked = true;

				MemoryCacheEntry entry;
				if (cache.TryGetValue (key, out entry) && entry != null) {
					perfCounters.Increment (MemoryCachePerformanceCounters.CACHE_HITS);
					if (entry.IsSliding)
						entry.UpdateSlidingExpiry ();

					return entry.Value;
				}
				perfCounters.Increment (MemoryCachePerformanceCounters.CACHE_MISSES);
				
				cache_lock.EnterWriteLock ();
				writeLocked = true;

				if (policy == null)
					entry = new MemoryCacheEntry (owner, key, value);
				else
					entry = new MemoryCacheEntry (owner, key, value,
								      policy.AbsoluteExpiration,
								      policy.ChangeMonitors,
								      policy.Priority,
								      policy.RemovedCallback,
								      policy.SlidingExpiration,
								      policy.UpdateCallback);

				AddToCache (key, entry);
				return null;
			} finally {
				if (writeLocked)
					cache_lock.ExitWriteLock ();
				if (readLocked)
					cache_lock.ExitUpgradeableReadLock ();
			}
		}
 internal MemoryCacheEntry Remove(MemoryCacheKey key, MemoryCacheEntry entryToRemove, CacheEntryRemovedReason reason) {
     MemoryCacheEntry entry = null;
     lock (_entriesLock) {
         if (_disposed == 0) {
             // get current entry
             entry = _entries[key] as MemoryCacheEntry;
             // remove if it matches the entry to be removed (but always remove if entryToRemove is null)
             if (entryToRemove == null || Object.ReferenceEquals(entry, entryToRemove)) {
                 // Dev10 865887: MemoryCache.Remove("\ue637\ud22a\u3e17") causes NullReferenceEx
                 if (entry != null) {
                     entry.State = EntryState.RemovingFromCache;
                     _entries.Remove(key);
                 }
             }
             else {
                 entry = null;
             }
         }
     }
     // release outside of lock
     RemoveFromCache(entry, reason);
     return entry;
 }
Example #57
0
		public void Set (string key, object value, CacheItemPolicy policy)
		{
			bool locked = false;
			try {
				cache_lock.EnterWriteLock ();
				locked = true;

				MemoryCacheEntry mce;
				bool update = false;
				if (cache.TryGetValue (key, out mce)) {
					if (mce != null) {
						perfCounters.Increment (MemoryCachePerformanceCounters.CACHE_HITS);
						mce.Value = value;
						mce.SetPolicy (policy);
						if (mce.IsExpirable)
							UpdateExpirable (mce);
						lru.Update (mce);
						return;
					}

					update = true;
				}
				perfCounters.Increment (MemoryCachePerformanceCounters.CACHE_MISSES);
				if (policy != null)
					mce = new MemoryCacheEntry (owner, key, value,
								    policy.AbsoluteExpiration,
								    policy.ChangeMonitors,
								    policy.Priority,
								    policy.RemovedCallback,
								    policy.SlidingExpiration,
								    policy.UpdateCallback);
				else
					mce = new MemoryCacheEntry (owner, key, value);
				AddToCache (key, mce, update);
			} finally {
				if (locked)
					cache_lock.ExitWriteLock ();
			}
		}
 internal void Remove(MemoryCacheEntry cacheEntry)
 {
     byte expiresBucket = cacheEntry.ExpiresBucket;
     if (expiresBucket != 0xff)
     {
         this._buckets[expiresBucket].RemoveCacheEntry(cacheEntry);
     }
 }
 // Associates this entry with an update sentinel. If this entry has a sliding expiration, we need to
 // touch the sentinel so that it doesn't expire.
 internal void ConfigureUpdateSentinel(MemoryCacheStore sentinelStore, MemoryCacheEntry sentinelEntry) {
     lock (this) {
         if (_fields == null) {
             _fields = new SeldomUsedFields();
         }
         _fields._updateSentinel = Tuple.Create(sentinelStore, sentinelEntry);
     }
 }
        // 'updatePerfCounters' defaults to true since this method is called by all Get() operations
        // to update both the performance counters and the sliding expiration. Callers that perform
        // nested sliding expiration updates (like a MemoryCacheEntry touching its update sentinel)
        // can pass false to prevent these from unintentionally showing up in the perf counters.
        internal void UpdateExpAndUsage(MemoryCacheEntry entry, bool updatePerfCounters = true) {
            if (entry != null) {
                if (entry.InUsage() || entry.SlidingExp > TimeSpan.Zero) {
                    DateTime utcNow = DateTime.UtcNow;
                    entry.UpdateSlidingExp(utcNow, _expires);
                    entry.UpdateUsage(utcNow, _usage);
                }

                // DevDiv #67021: If this entry has an update sentinel, the sliding expiration is actually associated
                // with that sentinel, not with this entry. We need to update the sentinel's sliding expiration to
                // keep the sentinel from expiring, which in turn would force a removal of this entry from the cache.
                entry.UpdateSlidingExpForUpdateSentinel();

                if (updatePerfCounters && _perfCounters != null) {
                    _perfCounters.Increment(PerfCounterName.Hits);
                    _perfCounters.Increment(PerfCounterName.HitRatio);
                    _perfCounters.Increment(PerfCounterName.HitRatioBase);
                }
            }
            else {
                if (updatePerfCounters && _perfCounters != null) {
                    _perfCounters.Increment(PerfCounterName.Misses);
                    _perfCounters.Increment(PerfCounterName.HitRatioBase);
                }
            }
        }