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()); }
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); } } } } }
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); } }
internal MemoryCacheEntry(string key, object value, DateTimeOffset absExp, TimeSpan slidingExp, CacheItemPriority priority, Collection <ChangeMonitor> dependencies, CacheEntryRemovedCallback removedCallback, MemoryCache cache) : base(key) { if (value is null) { throw new ArgumentNullException(nameof(value)); } _utcCreated = DateTime.UtcNow; _value = value; _slidingExp = slidingExp; if (_slidingExp > TimeSpan.Zero) { _utcAbsExp = _utcCreated + _slidingExp; } else { _utcAbsExp = absExp.UtcDateTime; } _expiresEntryRef = ExpiresEntryRef.INVALID; _expiresBucket = 0xff; _usageEntryRef = UsageEntryRef.INVALID; if (priority == CacheItemPriority.NotRemovable) { _usageBucket = 0xff; } else { _usageBucket = 0; } _callback = removedCallback; // CacheItemPolicy.ChangeMonitors is frequently the source for 'dependencies', and that property // is never null. So check that the collection of dependencies is not empty before allocating // the 'seldom' used fields. if (dependencies != null && dependencies.Count > 0) { _fields = new SeldomUsedFields(); _fields._dependencies = dependencies; _fields._cache = cache; } }
private void Reduce() { int num4; if ((this._cEntriesInUse >= this._minEntriesInUse) || this._blockReduce) { return; } int num = 0x3f; int num2 = this._freeEntryList._tail; int index = this._freeEntryList._head; Label_0032: num4 = this._pages[index]._pageNext; if (this._pages[index]._entries[0]._cFree > num) { this.MoveToListTail(index, ref this._freeEntryList); } else { this.MoveToListHead(index, ref this._freeEntryList); } if (index != num2) { index = num4; goto Label_0032; } while (this._freeEntryList._tail != -1) { ExpiresEntry[] entryArray = this._pages[this._freeEntryList._tail]._entries; int num5 = ((this._cPagesInUse * 0x7f) - entryArray[0]._cFree) - this._cEntriesInUse; if (num5 < (0x7f - entryArray[0]._cFree)) { return; } for (int i = 1; i < entryArray.Length; i++) { if (entryArray[i]._cacheEntry != null) { ExpiresEntryRef freeExpiresEntry = this.GetFreeExpiresEntry(); entryArray[i]._cacheEntry.ExpiresEntryRef = freeExpiresEntry; this._pages[freeExpiresEntry.PageIndex]._entries[freeExpiresEntry.Index] = entryArray[i]; entryArray[0]._cFree++; } } this.RemovePage(this._freeEntryList._tail); } return; }
internal MemoryCacheEntry(String key, Object value, DateTimeOffset absExp, TimeSpan slidingExp, CacheItemPriority priority, Collection <ChangeMonitor> dependencies, CacheEntryRemovedCallback removedCallback, MemoryCache cache) : base(key) { if (value == null) { throw new ArgumentNullException("value"); } _utcCreated = DateTime.UtcNow; _value = value; _slidingExp = slidingExp; if (_slidingExp > TimeSpan.Zero) { _utcAbsExp = _utcCreated + _slidingExp; } else { _utcAbsExp = absExp.UtcDateTime; } _expiresEntryRef = ExpiresEntryRef.INVALID; _expiresBucket = 0xff; _usageEntryRef = UsageEntryRef.INVALID; if (priority == CacheItemPriority.NotRemovable) { _usageBucket = 0xff; } else { _usageBucket = 0; } _callback = removedCallback; if (dependencies != null) { _fields = new SeldomUsedFields(); _fields._dependencies = dependencies; _fields._cache = cache; } }
internal void UtcUpdateCacheEntry(MemoryCacheEntry cacheEntry, DateTime utcExpires) { lock (this) { ExpiresEntryRef expiresEntryRef = cacheEntry.ExpiresEntryRef; if ((cacheEntry.ExpiresBucket == this._bucket) && !expiresEntryRef.IsInvalid) { ExpiresEntry[] entryArray = this._pages[expiresEntryRef.PageIndex]._entries; int index = expiresEntryRef.Index; this.RemoveCount(entryArray[index]._utcExpires); this.AddCount(utcExpires); entryArray[index]._utcExpires = utcExpires; cacheEntry.UtcAbsExp = utcExpires; } } }
internal void AddCacheEntry(MemoryCacheEntry cacheEntry) { lock (this) { if ((cacheEntry.State & (EntryState.AddedToCache | EntryState.AddingToCache)) == 0) { return; } ExpiresEntryRef entryRef = cacheEntry.ExpiresEntryRef; Debug.Assert((cacheEntry.ExpiresBucket == 0xff) == entryRef.IsInvalid, "(cacheEntry.ExpiresBucket == 0xff) == entryRef.IsInvalid"); if (cacheEntry.ExpiresBucket != 0xff || !entryRef.IsInvalid) { return; } if (_freeEntryList._head == -1) { Expand(); } ExpiresEntryRef freeRef = GetFreeExpiresEntry(); Debug.Assert(cacheEntry.ExpiresBucket == 0xff, "cacheEntry.ExpiresBucket == 0xff"); Debug.Assert(cacheEntry.ExpiresEntryRef.IsInvalid, "cacheEntry.ExpiresEntryRef.IsInvalid"); cacheEntry.ExpiresBucket = _bucket; cacheEntry.ExpiresEntryRef = freeRef; ExpiresEntry[] entries = (_pages[(freeRef.PageIndex)]._entries); int entryIndex = freeRef.Index; entries[entryIndex]._cacheEntry = cacheEntry; entries[entryIndex]._utcExpires = cacheEntry.UtcAbsExp; AddCount(cacheEntry.UtcAbsExp); _cEntriesInUse++; if ((cacheEntry.State & (EntryState.AddedToCache | EntryState.AddingToCache)) == 0) { RemoveCacheEntryNoLock(cacheEntry); } } }
private void RemoveCacheEntryNoLock(MemoryCacheEntry cacheEntry) { ExpiresEntryRef expiresEntryRef = cacheEntry.ExpiresEntryRef; if ((cacheEntry.ExpiresBucket == this._bucket) && !expiresEntryRef.IsInvalid) { ExpiresEntry[] entryArray = this._pages[expiresEntryRef.PageIndex]._entries; int index = expiresEntryRef.Index; this.RemoveCount(entryArray[index]._utcExpires); cacheEntry.ExpiresBucket = 0xff; cacheEntry.ExpiresEntryRef = ExpiresEntryRef.INVALID; entryArray[index]._cacheEntry = null; this.AddExpiresEntryToFreeList(expiresEntryRef); if (this._cEntriesInUse == 0) { this.ResetCounts(DateTime.UtcNow); } this.Reduce(); } }
private void AddExpiresEntryToFreeList(ExpiresEntryRef entryRef) { ExpiresEntry[] entryArray = this._pages[entryRef.PageIndex]._entries; int index = entryRef.Index; entryArray[index]._cFree = 0; entryArray[index]._next = entryArray[0]._next; entryArray[0]._next = entryRef; this._cEntriesInUse--; int pageIndex = entryRef.PageIndex; entryArray[0]._cFree++; if (entryArray[0]._cFree == 1) { this.AddToListHead(pageIndex, ref this._freeEntryList); } else if (entryArray[0]._cFree == 0x7f) { this.RemovePage(pageIndex); } }
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; Debug.Assert(cacheEntry == entries[entryIndex]._cacheEntry); RemoveCount(entries[entryIndex]._utcExpires); AddCount(utcExpires); entries[entryIndex]._utcExpires = utcExpires; cacheEntry.UtcAbsExp = utcExpires; } }
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(); Dbg.Trace("CacheExpiresRemove", "Removed item=" + cacheEntry.Key + ",_bucket=" + _bucket + ",ref=" + entryRef + ",now=" + Dbg.FormatLocalDate(DateTime.Now) + ",expires=" + cacheEntry.UtcAbsExp.ToLocalTime()); Dbg.Validate("CacheValidateExpires", this); Dbg.Dump("CacheExpiresRemove", this); }
private void AddExpiresEntryToFreeList(ExpiresEntryRef entryRef) { ExpiresEntry[] entries = (_pages[(entryRef.PageIndex)]._entries); int entryIndex = entryRef.Index; Debug.Assert(entries[entryIndex]._cacheEntry == null, "entries[entryIndex]._cacheEntry == null"); entries[entryIndex]._cFree = 0; entries[entryIndex]._next = ((entries)[0]._next); ((entries)[0]._next) = entryRef; _cEntriesInUse--; int pageIndex = entryRef.PageIndex; ((entries)[0]._cFree)++; if (((entries)[0]._cFree) == 1) { AddToListHead(pageIndex, ref _freeEntryList); } else if (((entries)[0]._cFree) == NUM_ENTRIES) { RemovePage(pageIndex); } }
static ExpiresEntryRef() { INVALID = new ExpiresEntryRef(0, 0); }
internal int FlushExpiredItems(DateTime utcNow, bool useInsertBlock) { if (_cEntriesInUse == 0 || GetExpiresCount(utcNow) == 0) { return(0); } Debug.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0"); ExpiresEntryRef inFlushHead = ExpiresEntryRef.INVALID; ExpiresEntry[] entries; int entryIndex; MemoryCacheEntry cacheEntry; int flushed = 0; try { if (useInsertBlock) { _cacheExpires.MemoryCacheStore.BlockInsert(); } lock (this) { Debug.Assert(_blockReduce == false, "_blockReduce == false"); if (_cEntriesInUse == 0 || GetExpiresCount(utcNow) == 0) { return(0); } ResetCounts(utcNow); int cPages = _cPagesInUse; for (int i = 0; i < _pages.Length; i++) { entries = _pages[i]._entries; if (entries != null) { int cEntries = NUM_ENTRIES - ((entries)[0]._cFree); for (int j = 1; j < entries.Length; j++) { cacheEntry = entries[j]._cacheEntry; if (cacheEntry != null) { if (entries[j]._utcExpires > utcNow) { AddCount(entries[j]._utcExpires); } else { cacheEntry.ExpiresBucket = 0xff; cacheEntry.ExpiresEntryRef = ExpiresEntryRef.INVALID; entries[j]._cFree = 1; entries[j]._next = inFlushHead; inFlushHead = new ExpiresEntryRef(i, j); flushed++; _cEntriesInFlush++; } cEntries--; if (cEntries == 0) { break; } } } cPages--; if (cPages == 0) { break; } } } if (flushed == 0) { Dbg.Trace("CacheExpiresFlushTotal", "FlushExpiredItems flushed " + flushed + " expired items, bucket=" + _bucket + "; Time=" + DateTime.Now.ToString("o", CultureInfo.InvariantCulture)); return(0); } _blockReduce = true; } } finally { if (useInsertBlock) { _cacheExpires.MemoryCacheStore.UnblockInsert(); } } Debug.Assert(!inFlushHead.IsInvalid, "!inFlushHead.IsInvalid"); MemoryCacheStore cacheStore = _cacheExpires.MemoryCacheStore; ExpiresEntryRef current = inFlushHead; ExpiresEntryRef next; while (!current.IsInvalid) { entries = (_pages[(current.PageIndex)]._entries); entryIndex = current.Index; next = entries[entryIndex]._next; cacheEntry = entries[entryIndex]._cacheEntry; entries[entryIndex]._cacheEntry = null; Debug.Assert(cacheEntry.ExpiresEntryRef.IsInvalid, "cacheEntry.ExpiresEntryRef.IsInvalid"); cacheStore.Remove(cacheEntry, cacheEntry, CacheEntryRemovedReason.Expired); current = next; } try { if (useInsertBlock) { _cacheExpires.MemoryCacheStore.BlockInsert(); } lock (this) { current = inFlushHead; while (!current.IsInvalid) { entries = (_pages[(current.PageIndex)]._entries); entryIndex = current.Index; next = entries[entryIndex]._next; _cEntriesInFlush--; AddExpiresEntryToFreeList(current); current = next; } Debug.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0"); _blockReduce = false; Reduce(); Dbg.Trace("CacheExpiresFlushTotal", "FlushExpiredItems flushed " + flushed + " expired items, bucket=" + _bucket + "; Time=" + DateTime.Now.ToString("o", CultureInfo.InvariantCulture)); } } finally { if (useInsertBlock) { _cacheExpires.MemoryCacheStore.UnblockInsert(); } } return(flushed); }
private void Reduce() { if (_cEntriesInUse >= _minEntriesInUse || _blockReduce) { return; } Debug.Assert(_freeEntryList._head != -1, "_freeEntryList._head != -1"); Debug.Assert(_freeEntryList._tail != -1, "_freeEntryList._tail != -1"); Debug.Assert(_freeEntryList._head != _freeEntryList._tail, "_freeEntryList._head != _freeEntryList._tail"); int meanFree = (int)(NUM_ENTRIES - (NUM_ENTRIES * MIN_LOAD_FACTOR)); int pageIndexLast = _freeEntryList._tail; int pageIndexCurrent = _freeEntryList._head; int pageIndexNext; ExpiresEntry[] entries; for (; ;) { pageIndexNext = (_pages[(pageIndexCurrent)]._pageNext); if ((((_pages[(pageIndexCurrent)]._entries))[0]._cFree) > meanFree) { MoveToListTail(pageIndexCurrent, ref _freeEntryList); } else { MoveToListHead(pageIndexCurrent, ref _freeEntryList); } if (pageIndexCurrent == pageIndexLast) { break; } pageIndexCurrent = pageIndexNext; } for (; ;) { if (_freeEntryList._tail == -1) { break; } entries = (_pages[(_freeEntryList._tail)]._entries); Debug.Assert(((entries)[0]._cFree) > 0, "FreeEntryCount(entries) > 0"); int availableFreeEntries = (_cPagesInUse * NUM_ENTRIES) - ((entries)[0]._cFree) - _cEntriesInUse; if (availableFreeEntries < (NUM_ENTRIES - ((entries)[0]._cFree))) { break; } for (int i = 1; i < entries.Length; i++) { if (entries[i]._cacheEntry == null) { continue; } Debug.Assert(_freeEntryList._head != _freeEntryList._tail, "_freeEntryList._head != _freeEntryList._tail"); ExpiresEntryRef newRef = GetFreeExpiresEntry(); Debug.Assert(newRef.PageIndex != _freeEntryList._tail, "newRef.PageIndex != _freeEntryList._tail"); MemoryCacheEntry cacheEntry = entries[i]._cacheEntry; cacheEntry.ExpiresEntryRef = newRef; ExpiresEntry[] newEntries = (_pages[(newRef.PageIndex)]._entries); newEntries[newRef.Index] = entries[i]; ((entries)[0]._cFree)++; } RemovePage(_freeEntryList._tail); } }
internal int FlushExpiredItems(DateTime utcNow, bool useInsertBlock) { ExpiresEntry[] entryArray; int index; MemoryCacheEntry entry; ExpiresEntryRef ref3; ExpiresEntryRef ref4; if ((this._cEntriesInUse == 0) || (this.GetExpiresCount(utcNow) == 0)) { return(0); } ExpiresEntryRef iNVALID = ExpiresEntryRef.INVALID; int num2 = 0; try { if (useInsertBlock) { this._cacheExpires.MemoryCacheStore.BlockInsert(); } lock (this) { if ((this._cEntriesInUse == 0) || (this.GetExpiresCount(utcNow) == 0)) { return(0); } this.ResetCounts(utcNow); int num3 = this._cPagesInUse; for (int i = 0; i < this._pages.Length; i++) { entryArray = this._pages[i]._entries; if (entryArray != null) { int num5 = 0x7f - entryArray[0]._cFree; for (int j = 1; j < entryArray.Length; j++) { entry = entryArray[j]._cacheEntry; if (entry != null) { if (entryArray[j]._utcExpires > utcNow) { this.AddCount(entryArray[j]._utcExpires); } else { entry.ExpiresBucket = 0xff; entry.ExpiresEntryRef = ExpiresEntryRef.INVALID; entryArray[j]._cFree = 1; entryArray[j]._next = iNVALID; iNVALID = new ExpiresEntryRef(i, j); num2++; this._cEntriesInFlush++; } num5--; if (num5 == 0) { break; } } } num3--; if (num3 == 0) { break; } } } if (num2 == 0) { return(0); } this._blockReduce = true; } } finally { if (useInsertBlock) { this._cacheExpires.MemoryCacheStore.UnblockInsert(); } } MemoryCacheStore memoryCacheStore = this._cacheExpires.MemoryCacheStore; for (ref3 = iNVALID; !ref3.IsInvalid; ref3 = ref4) { entryArray = this._pages[ref3.PageIndex]._entries; index = ref3.Index; ref4 = entryArray[index]._next; entry = entryArray[index]._cacheEntry; entryArray[index]._cacheEntry = null; memoryCacheStore.Remove(entry, entry, CacheEntryRemovedReason.Expired); } try { if (useInsertBlock) { this._cacheExpires.MemoryCacheStore.BlockInsert(); } lock (this) { for (ref3 = iNVALID; !ref3.IsInvalid; ref3 = ref4) { entryArray = this._pages[ref3.PageIndex]._entries; index = ref3.Index; ref4 = entryArray[index]._next; this._cEntriesInFlush--; this.AddExpiresEntryToFreeList(ref3); } this._blockReduce = false; this.Reduce(); } } finally { if (useInsertBlock) { this._cacheExpires.MemoryCacheStore.UnblockInsert(); } } return(num2); }
internal MemoryCacheEntry(String key, Object value, DateTimeOffset absExp, TimeSpan slidingExp, CacheItemPriority priority, Collection<ChangeMonitor> dependencies, CacheEntryRemovedCallback removedCallback, MemoryCache cache) : base(key) { if (value == null) { throw new ArgumentNullException("value"); } _utcCreated = DateTime.UtcNow; _value = value; _slidingExp = slidingExp; if (_slidingExp > TimeSpan.Zero) { _utcAbsExp = _utcCreated + _slidingExp; } else { _utcAbsExp = absExp.UtcDateTime; } _expiresEntryRef = ExpiresEntryRef.INVALID; _expiresBucket = 0xff; _usageEntryRef = UsageEntryRef.INVALID; if (priority == CacheItemPriority.NotRemovable) { _usageBucket = 0xff; } else { _usageBucket = 0; } _callback = removedCallback; if (dependencies != null) { _fields = new SeldomUsedFields(); _fields._dependencies = dependencies; _fields._cache = cache; } }