internal void UpdateUsage(DateTime utcNow, CacheUsage usage) { // update, but not more frequently than once per second. if (InUsage() && _utcLastUpdateUsage < utcNow - CacheUsage.CORRELATED_REQUEST_TIMEOUT) { _utcLastUpdateUsage = utcNow; usage.Update(this); if (_fields != null && _fields._dependencies != null) { foreach (ChangeMonitor monitor in _fields._dependencies) { MemoryCacheEntryChangeMonitor m = monitor as MemoryCacheEntryChangeMonitor; if (m == null) { continue; } foreach (MemoryCacheEntry e in m.Dependencies) { MemoryCacheStore store = e._fields._cache.GetStore(e); e.UpdateUsage(utcNow, store.Usage); } } } } }
private void InitDisposableMembers(NameValueCollection config) { bool dispose = true; try { try { _perfCounters = new PerfCounters(_name); } catch { // ignore exceptions from perf counters } for (int i = 0; i < _stores.Length; i++) { _stores[i] = new MemoryCacheStore(this, _perfCounters); } _stats = new MemoryCacheStatistics(this, config); AppDomain appDomain = Thread.GetDomain(); EventHandler onAppDomainUnload = new EventHandler(OnAppDomainUnload); appDomain.DomainUnload += onAppDomainUnload; _onAppDomainUnload = onAppDomainUnload; UnhandledExceptionEventHandler onUnhandledException = new UnhandledExceptionEventHandler(OnUnhandledException); appDomain.UnhandledException += onUnhandledException; _onUnhandledException = onUnhandledException; dispose = false; } finally { if (dispose) { Dispose(); } } }
internal MemoryCacheEntry RemoveEntry(string key, MemoryCacheEntry entry, CacheEntryRemovedReason reason) { MemoryCacheKey cacheKey = new MemoryCacheKey(key); MemoryCacheStore store = GetStore(cacheKey); return(store.Remove(cacheKey, entry, reason)); }
// 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 CacheUsage(MemoryCacheStore cacheStore) { _cacheStore = cacheStore; _buckets = new UsageBucket[NUMBUCKETS]; for (byte b = 0; b < _buckets.Length; b++) { _buckets[b] = new UsageBucket(this, b); } }
internal MemoryCacheEntry GetEntry(string key) { if (IsDisposed) { return(null); } MemoryCacheKey cacheKey = new MemoryCacheKey(key); MemoryCacheStore store = GetStore(cacheKey); return(store.Get(cacheKey)); }
public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null) { if (regionName != null) { throw new NotSupportedException(SR.RegionName_not_supported); } if (key == null) { throw new ArgumentNullException(nameof(key)); } DateTimeOffset absExp = ObjectCache.InfiniteAbsoluteExpiration; TimeSpan slidingExp = ObjectCache.NoSlidingExpiration; CacheItemPriority priority = CacheItemPriority.Default; Collection <ChangeMonitor> changeMonitors = null; CacheEntryRemovedCallback removedCallback = null; if (policy != null) { ValidatePolicy(policy); if (policy.UpdateCallback != null) { Set(key, value, policy.ChangeMonitors, policy.AbsoluteExpiration, policy.SlidingExpiration, policy.UpdateCallback); return; } absExp = policy.AbsoluteExpiration; slidingExp = policy.SlidingExpiration; priority = policy.Priority; changeMonitors = policy.ChangeMonitors; removedCallback = policy.RemovedCallback; } if (IsDisposed) { if (changeMonitors != null) { foreach (ChangeMonitor monitor in changeMonitors) { if (monitor != null) { monitor.Dispose(); } } } IsDisposedOrThrow(); return; } MemoryCacheKey cacheKey = new MemoryCacheKey(key); MemoryCacheStore store = GetStore(cacheKey); store.Set(cacheKey, new MemoryCacheEntry(key, value, absExp, slidingExp, priority, changeMonitors, removedCallback, this)); }
internal CacheExpires(MemoryCacheStore cacheStore) { Debug.Assert(NUMBUCKETS < byte.MaxValue); DateTime utcNow = DateTime.UtcNow; _cacheStore = cacheStore; _buckets = new ExpiresBucket[NUMBUCKETS]; for (byte b = 0; b < _buckets.Length; b++) { _buckets[b] = new ExpiresBucket(this, b, utcNow); } }
private object AddOrGetExistingInternal(string key, object value, CacheItemPolicy policy) { if (key is null) { throw new ArgumentNullException(nameof(key)); } DateTimeOffset absExp = ObjectCache.InfiniteAbsoluteExpiration; TimeSpan slidingExp = ObjectCache.NoSlidingExpiration; CacheItemPriority priority = CacheItemPriority.Default; Collection <ChangeMonitor> changeMonitors = null; CacheEntryRemovedCallback removedCallback = null; if (policy != null) { ValidatePolicy(policy); if (policy.UpdateCallback != null) { throw new ArgumentException(SR.Update_callback_must_be_null, nameof(policy)); } absExp = policy.AbsoluteExpiration; slidingExp = policy.SlidingExpiration; priority = policy.Priority; changeMonitors = policy.ChangeMonitors; removedCallback = policy.RemovedCallback; } if (IsDisposed) { if (changeMonitors != null) { foreach (ChangeMonitor monitor in changeMonitors) { if (monitor != null) { monitor.Dispose(); } } } IsDisposedOrThrow(); return(null); } MemoryCacheKey cacheKey = new MemoryCacheKey(key); MemoryCacheStore store = GetStore(cacheKey); MemoryCacheEntry entry = store.AddOrGetExisting(cacheKey, new MemoryCacheEntry(key, value, absExp, slidingExp, priority, changeMonitors, removedCallback, this)); return((entry != null) ? entry.Value : null); }
internal void UpdateSlidingExpForUpdateSentinel() { // We don't need a lock to get information about the update sentinel SeldomUsedFields fields = _fields; if (fields != null) { Tuple <MemoryCacheStore, MemoryCacheEntry> sentinelInfo = fields._updateSentinel; // touch the update sentinel to keep it from expiring if (sentinelInfo != null) { MemoryCacheStore sentinelStore = sentinelInfo.Item1; MemoryCacheEntry sentinelEntry = sentinelInfo.Item2; sentinelStore.UpdateExpAndUsage(sentinelEntry, updatePerfCounters: false); // perf counters shouldn't be polluted by touching update sentinel entry } } }
internal void UpdateUsage(DateTime utcNow, CacheUsage usage) { if (this.InUsage() && (this._utcLastUpdateUsage < (utcNow - CacheUsage.CORRELATED_REQUEST_TIMEOUT))) { this._utcLastUpdateUsage = utcNow; usage.Update(this); if ((this._fields != null) && (this._fields._dependencies != null)) { foreach (ChangeMonitor monitor in this._fields._dependencies) { MemoryCacheEntryChangeMonitor monitor2 = monitor as MemoryCacheEntryChangeMonitor; if (monitor2 != null) { foreach (MemoryCacheEntry entry in monitor2.Dependencies) { MemoryCacheStore store = entry._fields._cache.GetStore(entry); entry.UpdateUsage(utcNow, store.Usage); } } } } } }
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); }
internal int FlushUnderUsedItems(int maxFlush, bool force) { UsageEntry[] entryArray; int num; UsageEntryRef ref6; UsageEntryRef ref7; if (this._cEntriesInUse == 0) { return(0); } UsageEntryRef iNVALID = UsageEntryRef.INVALID; int num2 = 0; try { this._cacheUsage.MemoryCacheStore.BlockInsert(); lock (this) { UsageEntryRef ref4; if (this._cEntriesInUse == 0) { return(0); } DateTime utcNow = DateTime.UtcNow; for (UsageEntryRef ref3 = this._lastRefTail; (this._cEntriesInFlush < maxFlush) && !ref3.IsInvalid; ref3 = ref4) { for (ref4 = this._pages[ref3.PageIndex]._entries[ref3.Ref2Index]._ref2._prev; ref4.IsRef1; ref4 = this._pages[ref4.PageIndex]._entries[ref4.Ref1Index]._ref1._prev) { } entryArray = this._pages[ref3.PageIndex]._entries; num = ref3.Ref2Index; if (!force) { DateTime time = entryArray[num]._utcDate; if (((utcNow - time) <= CacheUsage.NEWADD_INTERVAL) && (utcNow >= time)) { continue; } } UsageEntryRef entryRef = new UsageEntryRef(ref3.PageIndex, ref3.Ref2Index); entryArray[num]._cacheEntry.UsageEntryRef = UsageEntryRef.INVALID; this.RemoveEntryFromLastRefList(entryRef); entryArray[num]._ref1._next = iNVALID; iNVALID = entryRef; num2++; this._cEntriesInFlush++; } if (num2 == 0) { return(0); } this._blockReduce = true; } } finally { this._cacheUsage.MemoryCacheStore.UnblockInsert(); } MemoryCacheStore memoryCacheStore = this._cacheUsage.MemoryCacheStore; for (ref6 = iNVALID; !ref6.IsInvalid; ref6 = ref7) { entryArray = this._pages[ref6.PageIndex]._entries; num = ref6.Ref1Index; ref7 = entryArray[num]._ref1._next; MemoryCacheEntry key = entryArray[num]._cacheEntry; entryArray[num]._cacheEntry = null; memoryCacheStore.Remove(key, key, CacheEntryRemovedReason.Evicted); } try { this._cacheUsage.MemoryCacheStore.BlockInsert(); lock (this) { for (ref6 = iNVALID; !ref6.IsInvalid; ref6 = ref7) { entryArray = this._pages[ref6.PageIndex]._entries; num = ref6.Ref1Index; ref7 = entryArray[num]._ref1._next; this._cEntriesInFlush--; this.AddUsageEntryToFreeList(ref6); } this._blockReduce = false; this.Reduce(); } } finally { this._cacheUsage.MemoryCacheStore.UnblockInsert(); } return(num2); }
internal void Set(string key, object value, Collection <ChangeMonitor> changeMonitors, DateTimeOffset absoluteExpiration, TimeSpan slidingExpiration, CacheEntryUpdateCallback onUpdateCallback) { if (key == null) { throw new ArgumentNullException(nameof(key)); } if (changeMonitors == null && absoluteExpiration == ObjectCache.InfiniteAbsoluteExpiration && slidingExpiration == ObjectCache.NoSlidingExpiration) { throw new ArgumentException(SR.Invalid_argument_combination); } if (onUpdateCallback == null) { throw new ArgumentNullException(nameof(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); }
internal int FlushUnderUsedItems(int maxFlush, bool force) { if (_cEntriesInUse == 0) { return(0); } Debug.Assert(maxFlush > 0, "maxFlush is not greater than 0, instead is " + maxFlush); Debug.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0"); UsageEntryRef inFlushHead = UsageEntryRef.INVALID; UsageEntryRef prev, prevNext; DateTime utcDate; UsageEntry[] entries; int entryIndex; MemoryCacheEntry cacheEntry; int flushed = 0; try { _cacheUsage.MemoryCacheStore.BlockInsert(); lock (this) { Debug.Assert(_blockReduce == false, "_blockReduce == false"); if (_cEntriesInUse == 0) { return(0); } DateTime utcNow = DateTime.UtcNow; for (prev = _lastRefTail; _cEntriesInFlush < maxFlush && !prev.IsInvalid; prev = prevNext) { Debug.Assert(_cEntriesInUse > 0, "_cEntriesInUse > 0"); prevNext = (_pages[(prev.PageIndex)]._entries)[prev.Ref2Index]._ref2._prev; while (prevNext.IsRef1) { prevNext = (_pages[(prevNext.PageIndex)]._entries)[prevNext.Ref1Index]._ref1._prev; } entries = (_pages[(prev.PageIndex)]._entries); entryIndex = prev.Ref2Index; if (!force) { utcDate = entries[entryIndex]._utcDate; Debug.Assert(utcDate != DateTime.MinValue, "utcDate != DateTime.MinValue"); if (utcNow - utcDate <= CacheUsage.NEWADD_INTERVAL && utcNow >= utcDate) { continue; } } UsageEntryRef prev1 = (new UsageEntryRef((prev).PageIndex, (prev).Ref2Index)); cacheEntry = entries[entryIndex]._cacheEntry; Debug.Assert(cacheEntry.UsageEntryRef == prev1, "cacheEntry.UsageEntryRef == prev1"); Dbg.Trace("CacheUsageFlushUnderUsedItem", "Flushing underused items, item=" + cacheEntry.Key + ", bucket=" + _bucket); cacheEntry.UsageEntryRef = UsageEntryRef.INVALID; RemoveEntryFromLastRefList(prev1); entries[entryIndex]._ref1._next = inFlushHead; inFlushHead = prev1; flushed++; _cEntriesInFlush++; } if (flushed == 0) { Dbg.Trace("CacheUsageFlushTotal", "Flush(" + maxFlush + "," + force + ") removed " + flushed + " underused items; Time=" + DateTime.Now.ToString("o", CultureInfo.InvariantCulture)); return(0); } _blockReduce = true; } } finally { _cacheUsage.MemoryCacheStore.UnblockInsert(); } Debug.Assert(!inFlushHead.IsInvalid, "!inFlushHead.IsInvalid"); MemoryCacheStore cacheStore = _cacheUsage.MemoryCacheStore; UsageEntryRef current = inFlushHead; UsageEntryRef next; while (!current.IsInvalid) { entries = (_pages[(current.PageIndex)]._entries); entryIndex = current.Ref1Index; next = entries[entryIndex]._ref1._next; cacheEntry = entries[entryIndex]._cacheEntry; entries[entryIndex]._cacheEntry = null; Debug.Assert(cacheEntry.UsageEntryRef.IsInvalid, "cacheEntry.UsageEntryRef.IsInvalid"); cacheStore.Remove(cacheEntry, cacheEntry, CacheEntryRemovedReason.Evicted); current = next; } try { _cacheUsage.MemoryCacheStore.BlockInsert(); lock (this) { current = inFlushHead; while (!current.IsInvalid) { entries = (_pages[(current.PageIndex)]._entries); entryIndex = current.Ref1Index; next = entries[entryIndex]._ref1._next; _cEntriesInFlush--; AddUsageEntryToFreeList(current); current = next; } Debug.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0"); _blockReduce = false; Reduce(); Dbg.Trace("CacheUsageFlushTotal", "Flush(" + maxFlush + "," + force + ") removed " + flushed + " underused items; Time=" + DateTime.Now.ToString("o", CultureInfo.InvariantCulture)); } } finally { _cacheUsage.MemoryCacheStore.UnblockInsert(); } return(flushed); }
protected CacheEntryCollection(MemoryCacheStore store, ICacheEntryHelper helper) { this.store = store; this.helper = helper; entries = new SortedSet <MemoryCacheEntry> (helper); }
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); }
public CacheExpires (MemoryCacheStore store) : base (store, helper) { }
// 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); } }
public CacheExpires(MemoryCacheStore store) : base(store, helper) { }