Exemplo n.º 1
0
        internal void SetEntry(CacheEntry entry)
        {
            if (_disposed)
            {
                // No-op instead of throwing since this is called during CacheEntry.Dispose
                return;
            }

            if (_options.SizeLimit.HasValue && !entry.Size.HasValue)
            {
                throw new InvalidOperationException(SR.Format(SR.CacheEntryHasEmptySize, nameof(entry.Size), nameof(_options.SizeLimit)));
            }

            DateTimeOffset utcNow = _options.Clock.UtcNow;

            // 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 (entry.AbsoluteExpirationRelativeToNow.HasValue)
            {
                var absoluteExpiration = utcNow + entry.AbsoluteExpirationRelativeToNow.Value;
                if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration < entry.AbsoluteExpiration.Value)
                {
                    entry.AbsoluteExpiration = absoluteExpiration;
                }
            }

            // Initialize the last access timestamp at the time the entry is added
            entry.LastAccessed = utcNow;

            CoherentState coherentState = _coherentState; // Clear() can update the reference in the meantime

            if (coherentState._entries.TryGetValue(entry.Key, out CacheEntry priorEntry))
            {
                priorEntry.SetExpired(EvictionReason.Replaced);
            }

            if (entry.CheckExpired(utcNow))
            {
                entry.InvokeEvictionCallbacks();
                if (priorEntry != null)
                {
                    coherentState.RemoveEntry(priorEntry, _options);
                }
                StartScanForExpiredItemsIfNeeded(utcNow);
                return;
            }

            bool exceedsCapacity = UpdateCacheSizeExceedsCapacity(entry, coherentState);

            if (!exceedsCapacity)
            {
                bool entryAdded = false;

                if (priorEntry == null)
                {
                    // Try to add the new entry if no previous entries exist.
                    entryAdded = coherentState._entries.TryAdd(entry.Key, entry);
                }
                else
                {
                    // Try to update with the new entry if a previous entries exist.
                    entryAdded = coherentState._entries.TryUpdate(entry.Key, entry, priorEntry);

                    if (entryAdded)
                    {
                        if (_options.SizeLimit.HasValue)
                        {
                            // The prior entry was removed, decrease the by the prior entry's size
                            Interlocked.Add(ref coherentState._cacheSize, -priorEntry.Size.Value);
                        }
                    }
                    else
                    {
                        // The update will fail if the previous entry was removed after retrival.
                        // Adding the new entry will succeed only if no entry has been added since.
                        // This guarantees removing an old entry does not prevent adding a new entry.
                        entryAdded = coherentState._entries.TryAdd(entry.Key, entry);
                    }
                }

                if (entryAdded)
                {
                    entry.AttachTokens();
                }
                else
                {
                    if (_options.SizeLimit.HasValue)
                    {
                        // Entry could not be added, reset cache size
                        Interlocked.Add(ref coherentState._cacheSize, -entry.Size.Value);
                    }
                    entry.SetExpired(EvictionReason.Replaced);
                    entry.InvokeEvictionCallbacks();
                }

                if (priorEntry != null)
                {
                    priorEntry.InvokeEvictionCallbacks();
                }
            }
            else
            {
                entry.SetExpired(EvictionReason.Capacity);
                TriggerOvercapacityCompaction();
                entry.InvokeEvictionCallbacks();
                if (priorEntry != null)
                {
                    coherentState.RemoveEntry(priorEntry, _options);
                }
            }

            StartScanForExpiredItemsIfNeeded(utcNow);
        }
Exemplo n.º 2
0
        private void SetEntry(CacheEntry entry)
        {
            var utcNow = _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;
            CacheEntry priorEntry;

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

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

            if (priorEntry != null)
            {
                priorEntry.InvokeEvictionCallbacks();
            }

            if (!added)
            {
                entry.InvokeEvictionCallbacks();
            }

            StartScanForExpiredItems();
        }
        private void SetEntry(CacheEntry entry)
        {
            if (_disposed)
            {
                // No-op instead of throwing since this is called during CacheEntry.Dispose
                return;
            }

            var utcNow = _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;

            CacheEntry priorEntry;

            if (_entries.TryGetValue(entry.Key, out priorEntry))
            {
                priorEntry.SetExpired(EvictionReason.Replaced);
            }

            if (!entry.CheckExpired(utcNow))
            {
                var entryAdded = false;

                if (priorEntry == null)
                {
                    // Try to add the new entry if no previous entries exist.
                    entryAdded = _entries.TryAdd(entry.Key, entry);
                }
                else
                {
                    // Try to update with the new entry if a previous entries exist.
                    entryAdded = _entries.TryUpdate(entry.Key, entry, priorEntry);

                    if (!entryAdded)
                    {
                        // The update will fail if the previous entry was removed after retrival.
                        // Adding the new entry will succeed only if no entry has been added since.
                        // This guarantees removing an old entry does not prevent adding a new entry.
                        entryAdded = _entries.TryAdd(entry.Key, entry);
                    }
                }

                if (entryAdded)
                {
                    entry.AttachTokens();
                }
                else
                {
                    entry.SetExpired(EvictionReason.Replaced);
                    entry.InvokeEvictionCallbacks();
                }

                if (priorEntry != null)
                {
                    priorEntry.InvokeEvictionCallbacks();
                }
            }
            else
            {
                entry.InvokeEvictionCallbacks();
                if (priorEntry != null)
                {
                    RemoveEntry(priorEntry);
                }
            }

            StartScanForExpiredItems();
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 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;
        }