예제 #1
0
        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
                }
            }
        }
예제 #2
0
 private void RemoveEntryFromMemoryAndStore(PersistentCacheEntry entry)
 {
     _InMemoryEntries.Remove(entry.Key);
     if (_Options.IsPersistent)
     {
         _Options.PersistentStore.RemoveEntry(entry.PersistentStoreId.Value);
     }
 }
예제 #3
0
 private void AddEntryToMemoryAndStore(PersistentCacheEntry entry)
 {
     _InMemoryEntries[entry.Key] = entry;
     if (_Options.IsPersistent && !_IsReloadingFromStore)
     {
         LiteDbCacheEntry liteDbEntry = CreateLiteDbEntryFromPersistentEntry(entry);
         entry.PersistentStoreId = _Options.PersistentStore.AddEntry(liteDbEntry);
     }
 }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
 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();
 }
예제 #7
0
 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;
     }
 }
예제 #8
0
 private void EntryExpired(PersistentCacheEntry entry)
 {
     // TODO: For efficiency consider processing these expirations in batches.
     RemoveEntry(entry);
     StartScanForExpiredItems();
 }
예제 #9
0
        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();
        }