private static void InvokeCallbacks(PersistentCacheEntry entry) { var callbackRegistrations = Interlocked.Exchange(ref entry._PostEvictionCallbacks, null); if (callbackRegistrations == null) { return; } for (int i = 0; i < callbackRegistrations.Count; i++) { var registration = callbackRegistrations[i]; try { registration.EvictionCallback?.Invoke(entry.Key, entry.Value, entry._EvictionReason, registration.State); } catch (Exception) { return; // This will be invoked on a background thread, don't let it throw. // TODO: LOG } } }
private void RemoveEntryFromMemoryAndStore(PersistentCacheEntry entry) { _InMemoryEntries.Remove(entry.Key); if (_Options.IsPersistent) { _Options.PersistentStore.RemoveEntry(entry.PersistentStoreId.Value); } }
private void AddEntryToMemoryAndStore(PersistentCacheEntry entry) { _InMemoryEntries[entry.Key] = entry; if (_Options.IsPersistent && !_IsReloadingFromStore) { LiteDbCacheEntry liteDbEntry = CreateLiteDbEntryFromPersistentEntry(entry); entry.PersistentStoreId = _Options.PersistentStore.AddEntry(liteDbEntry); } }
private LiteDbCacheEntry CreateLiteDbEntryFromPersistentEntry(PersistentCacheEntry entry) { Type cacheValueType = entry.Value?.GetType() ?? typeof(object); LiteDbCacheEntry liteDbEntry = LiteDbCacheEntry.ConstructCacheEntry(cacheValueType); liteDbEntry.CacheName = _Options.CacheName; liteDbEntry.Priority = entry.Priority; liteDbEntry.Key = entry.Key; liteDbEntry.LastAccessed = entry.LastAccessed; liteDbEntry.AbsoluteExpiration = entry.AbsoluteExpiration; liteDbEntry.SlidingExpiration = entry.SlidingExpiration; liteDbEntry.SetValue(entry.Value); return(liteDbEntry); }
public bool TryGetValue(object key, out object result) { if (key == null) { throw new ArgumentNullException(nameof(key)); } var utcNow = _Options.Clock.UtcNow; result = null; bool found = false; PersistentCacheEntry expiredEntry = null; CheckDisposed(); _EntryLock.EnterReadLock(); try { PersistentCacheEntry entry; if (_InMemoryEntries.TryGetValue(key, out entry)) { // Check if expired due to expiration tokens, timers, etc. and if so, remove it. if (entry.CheckExpired(utcNow)) { expiredEntry = entry; } else { found = true; entry.LastAccessed = utcNow; result = entry.Value; } } } finally { _EntryLock.ExitReadLock(); } if (expiredEntry != null) { // TODO: For efficiency queue this up for batch removal RemoveEntry(expiredEntry); } StartScanForExpiredItems(); return(found); }
private void RemoveEntry(PersistentCacheEntry entry) { _EntryLock.EnterWriteLock(); try { // Only remove it if someone hasn't modified it since our lookup PersistentCacheEntry currentEntry; if (_InMemoryEntries.TryGetValue(entry.Key, out currentEntry) && object.ReferenceEquals(currentEntry, entry)) { RemoveEntryFromMemoryAndStore(entry); if (_Options.IsPersistent) { entry.PropertyChanged -= Entry_PropertyChanged; } } } finally { _EntryLock.ExitWriteLock(); } entry.InvokeEvictionCallbacks(); }
private void ReloadDataFromStore() { try { _IsReloadingFromStore = true; List <Internal.LiteDbCacheEntry> persistentCacheEntries = _Options.PersistentStore.LoadEntries(_Options.CacheName); foreach (Internal.LiteDbCacheEntry persistentCacheEntry in persistentCacheEntries) { using (PersistentCacheEntry cacheEntry = (PersistentCacheEntry)CreateEntry(persistentCacheEntry.Key)) { cacheEntry.PersistentStoreId = persistentCacheEntry.Id; cacheEntry.Priority = persistentCacheEntry.Priority; cacheEntry.Value = persistentCacheEntry.GetValue(); cacheEntry.LastAccessed = persistentCacheEntry.LastAccessed; cacheEntry.AbsoluteExpiration = persistentCacheEntry.AbsoluteExpiration; cacheEntry.SlidingExpiration = persistentCacheEntry.SlidingExpiration; } } } finally { _IsReloadingFromStore = false; } }
private void EntryExpired(PersistentCacheEntry entry) { // TODO: For efficiency consider processing these expirations in batches. RemoveEntry(entry); StartScanForExpiredItems(); }
private void SetEntry(PersistentCacheEntry entry) { var utcNow = _Options.Clock.UtcNow; DateTimeOffset?absoluteExpiration = null; if (entry._AbsoluteExpirationRelativeToNow.HasValue) { absoluteExpiration = utcNow + entry._AbsoluteExpirationRelativeToNow; } else if (entry._AbsoluteExpiration.HasValue) { absoluteExpiration = entry._AbsoluteExpiration; } // Applying the option's absolute expiration only if it's not already smaller. // This can be the case if a dependent cache entry has a smaller value, and // it was set by cascading it to its parent. if (absoluteExpiration.HasValue) { if (!entry._AbsoluteExpiration.HasValue || absoluteExpiration.Value < entry._AbsoluteExpiration.Value) { entry._AbsoluteExpiration = absoluteExpiration; } } // Initialize the last access timestamp at the time the entry is added entry.LastAccessed = utcNow; var added = false; PersistentCacheEntry priorEntry; _EntryLock.EnterWriteLock(); try { if (_InMemoryEntries.TryGetValue(entry.Key, out priorEntry)) { RemoveEntryFromMemoryAndStore(priorEntry); priorEntry.SetExpired(EvictionReason.Replaced); } if (!entry.CheckExpired(utcNow)) { AddEntryToMemoryAndStore(entry); entry.AttachTokens(); if (_Options.IsPersistent) { entry.PropertyChanged += Entry_PropertyChanged; } added = true; } } finally { _EntryLock.ExitWriteLock(); } if (priorEntry != null) { priorEntry.InvokeEvictionCallbacks(); } if (!added) { entry.InvokeEvictionCallbacks(); } StartScanForExpiredItems(); }