Пример #1
0
 private void RemoveEntry(CacheEntry entry)
 {
     _entryLock.EnterWriteLock();
     try
     {
         // Only remove it if someone hasn't modified it since our lookup
         CacheEntry currentEntry;
         if (_entries.TryGetValue(entry.Key, out currentEntry)
             && object.ReferenceEquals(currentEntry, entry))
         {
             _entries.Remove(entry.Key);
         }
     }
     finally
     {
         _entryLock.ExitWriteLock();
     }
     entry.InvokeEvictionCallbacks();
 }
Пример #2
0
        public object Set(object key, object value, MemoryCacheEntryOptions cacheEntryOptions)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CheckDisposed();
            CacheEntry priorEntry = null;
            var utcNow = _clock.UtcNow;

            DateTimeOffset? absoluteExpiration = null;
            if (cacheEntryOptions.AbsoluteExpirationRelativeToNow.HasValue)
            {
                absoluteExpiration = utcNow + cacheEntryOptions.AbsoluteExpirationRelativeToNow;
            }
            else if (cacheEntryOptions.AbsoluteExpiration.HasValue)
            {
                if (cacheEntryOptions.AbsoluteExpiration <= utcNow)
                {
                    throw new ArgumentOutOfRangeException(
                        nameof(MemoryCacheEntryOptions.AbsoluteExpiration),
                        cacheEntryOptions.AbsoluteExpiration.Value,
                        "The absolute expiration value must be in the future.");
                }

                absoluteExpiration = cacheEntryOptions.AbsoluteExpiration;
            }

            var entry = new CacheEntry(
                key,
                value,
                utcNow,
                absoluteExpiration,
                cacheEntryOptions,
                _entryExpirationNotification);

            var link = EntryLinkHelpers.ContextLink;
            if (link != null)
            {
                // Copy expiration tokens and AbsoluteExpiration to the link.
                // We do this regardless of it gets cached because the tokens are associated with the value we'll return.
                if (entry.Options.ExpirationTokens != null)
                {
                    link.AddExpirationTokens(entry.Options.ExpirationTokens);
                }
                if (absoluteExpiration.HasValue)
                {
                    link.SetAbsoluteExpiration(absoluteExpiration.Value);
                }
            }

            bool added = false;

            _entryLock.EnterWriteLock();
            try
            {
                if (_entries.TryGetValue(key, out priorEntry))
                {
                    _entries.Remove(key);
                    priorEntry.SetExpired(EvictionReason.Replaced);
                }

                if (!entry.CheckExpired(utcNow))
                {
                    _entries[key] = entry;
                    entry.AttachTokens();
                    added = true;
                }
            }
            finally
            {
                _entryLock.ExitWriteLock();
            }
            if (priorEntry != null)
            {
                priorEntry.InvokeEvictionCallbacks();
            }
            if (!added)
            {
                entry.InvokeEvictionCallbacks();
            }

            StartScanForExpiredItems();

            return value;
        }
Пример #3
0
 private void EntryExpired(CacheEntry entry)
 {
     // TODO: For efficiency consider processing these expirations in batches.
     RemoveEntry(entry);
     StartScanForExpiredItems();
 }
Пример #4
0
        public object Set([NotNull] string key, IEntryLink link, object state, [NotNull] Func<ICacheSetContext, object> create)
        {
            CheckDisposed();
            CacheEntry priorEntry = null;
            var now = _clock.UtcNow;
            var context = new CacheSetContext(key) { State = state, CreationTime = now };
            object value = create(context);
            var entry = new CacheEntry(context, value, _entryExpirationNotification);
            bool added = false;

            if (link != null)
            {
                // Copy triggers and AbsoluteExpiration to the link.
                // We do this regardless of it gets cached because the triggers are associated with the value we'll return.
                if (entry.Context.Triggers != null)
                {
                    link.AddExpirationTriggers(entry.Context.Triggers);
                }
                if (entry.Context.AbsoluteExpiration.HasValue)
                {
                    link.SetAbsoluteExpiration(entry.Context.AbsoluteExpiration.Value);
                }
            }

            _entryLock.EnterWriteLock();
            try
            {
                if (_entries.TryGetValue(key, out priorEntry))
                {
                    _entries.Remove(key);
                    priorEntry.SetExpired(EvictionReason.Replaced);
                }

                if (!entry.CheckExpired(now))
                {
                    _entries[key] = entry;
                    entry.AttachTriggers();
                    added = true;
                }
            }
            finally
            {
                _entryLock.ExitWriteLock();
            }
            if (priorEntry != null)
            {
                priorEntry.InvokeEvictionCallbacks();
            }
            if (!added)
            {
                entry.InvokeEvictionCallbacks();
            }

            StartScanForExpiredItems();

            return value;
        }
Пример #5
0
        public object Set(object key, object value, MemoryCacheEntryOptions cacheEntryOptions)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            CheckDisposed();
            CacheEntry priorEntry = null;
            var        utcNow     = _clock.UtcNow;

            DateTimeOffset?absoluteExpiration = null;

            if (cacheEntryOptions.AbsoluteExpirationRelativeToNow.HasValue)
            {
                absoluteExpiration = utcNow + cacheEntryOptions.AbsoluteExpirationRelativeToNow;
            }
            else if (cacheEntryOptions.AbsoluteExpiration.HasValue)
            {
                if (cacheEntryOptions.AbsoluteExpiration <= utcNow)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(MemoryCacheEntryOptions.AbsoluteExpiration),
                              cacheEntryOptions.AbsoluteExpiration.Value,
                              "The absolute expiration value must be in the future.");
                }

                absoluteExpiration = cacheEntryOptions.AbsoluteExpiration;
            }

            var entry = new CacheEntry(
                key,
                value,
                utcNow,
                absoluteExpiration,
                cacheEntryOptions,
                _entryExpirationNotification);

            var link = EntryLinkHelpers.ContextLink;

            if (link != null)
            {
                // Copy expiration tokens and AbsoluteExpiration to the link.
                // We do this regardless of it gets cached because the tokens are associated with the value we'll return.
                if (entry.Options.ExpirationTokens != null)
                {
                    link.AddExpirationTokens(entry.Options.ExpirationTokens);
                }
                if (absoluteExpiration.HasValue)
                {
                    link.SetAbsoluteExpiration(absoluteExpiration.Value);
                }
            }

            bool added = false;

            _entryLock.EnterWriteLock();
            try
            {
                if (_entries.TryGetValue(key, out priorEntry))
                {
                    _entries.Remove(key);
                    priorEntry.SetExpired(EvictionReason.Replaced);
                }

                if (!entry.CheckExpired(utcNow))
                {
                    _entries[key] = entry;
                    entry.AttachTokens();
                    added = true;
                }
            }
            finally
            {
                _entryLock.ExitWriteLock();
            }
            if (priorEntry != null)
            {
                priorEntry.InvokeEvictionCallbacks();
            }
            if (!added)
            {
                entry.InvokeEvictionCallbacks();
            }

            StartScanForExpiredItems();

            return(value);
        }
Пример #6
0
 private void EntryExpired(CacheEntry entry)
 {
     // TODO: For efficiency consider processing these expirations in batches.
     RemoveEntry(entry);
     StartScanForExpiredItems();
 }
Пример #7
0
        public bool TryGetValue(object key, out object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            value = null;
            CacheEntry expiredEntry = null;
            bool       found        = false;

            CheckDisposed();
            _entryLock.EnterReadLock();
            try
            {
                CacheEntry entry;
                if (_entries.TryGetValue(key, out entry))
                {
                    // Check if expired due to expiration tokens, timers, etc. and if so, remove it.
                    if (entry.CheckExpired(_clock.UtcNow))
                    {
                        expiredEntry = entry;
                    }
                    else
                    {
                        // Refresh sliding expiration, etc.
                        entry.LastAccessed = _clock.UtcNow;
                        value = entry.Value;
                        found = true;

                        var link = EntryLinkHelpers.ContextLink;
                        if (link != null)
                        {
                            // Copy expiration tokens and AbsoluteExpiration to the link
                            if (entry.Options.ExpirationTokens != null)
                            {
                                link.AddExpirationTokens(entry.Options.ExpirationTokens);
                            }
                            if (entry.Options.AbsoluteExpiration.HasValue)
                            {
                                link.SetAbsoluteExpiration(entry.Options.AbsoluteExpiration.Value);
                            }
                        }
                    }
                }
            }
            finally
            {
                _entryLock.ExitReadLock();
            }

            if (expiredEntry != null)
            {
                // TODO: For efficiency queue this up for batch removal
                RemoveEntry(expiredEntry);
            }

            StartScanForExpiredItems();

            return(found);
        }
Пример #8
0
        private static void InvokeCallbacks(CacheEntry entry)
        {
            var callbackRegistrations = entry.PostEvictionCallbacks;
            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)
                {
                    // This will be invoked on a background thread, don't let it throw.
                    // TODO: LOG
                }
            }
        }