/// <summary> /// The given callback will be fired after the cache entry is evicted from the cache. /// </summary> /// <param name="options"></param> /// <param name="callback"></param> public static CacheEntryOptions RegisterPostEvictionCallback(this CacheEntryOptions options, CacheEntryEvictionDelegate callback) { if (callback == null) { throw new ArgumentNullException(nameof(callback)); } options.PostEvictionCallbacks.Add(callback); return(options); }
/// <summary> /// Expire the cache entry if the given <see cref="IChangeToken"/> expires. /// </summary> /// <param name="options">The <see cref="MemoryCacheEntryOptions"/>.</param> /// <param name="expirationToken">The <see cref="IChangeToken"/> that causes the cache entry to expire.</param> public static CacheEntryOptions AddDependency(this CacheEntryOptions options, string dependency) { if (string.IsNullOrEmpty(dependency)) { throw new ArgumentNullException(nameof(dependency)); } if (!options.Dependencies.Contains(dependency)) { options.Dependencies.Add(dependency); } return(options); }
/// <summary> /// Sets how long the cache entry can be inactive (e.g. not accessed) before it will be removed. /// This will not extend the entry lifetime beyond the absolute expiration (if set). /// </summary> /// <param name="options"></param> /// <param name="offset"></param> public static CacheEntryOptions SetSlidingExpiration(this CacheEntryOptions options, TimeSpan offset) { options.SlidingExpiration = offset; return(options); }
/// <summary> /// Sets an absolute expiration date for the cache entry. /// </summary> /// <param name="options"></param> /// <param name="absolute"></param> public static CacheEntryOptions SetAbsoluteExpiration(this CacheEntryOptions options, DateTimeOffset absolute) { options.AbsoluteExpiration = absolute; return(options); }
/// <summary> /// Sets an absolute expiration time, relative to now. /// </summary> /// <param name="options"></param> /// <param name="relative"></param> public static CacheEntryOptions SetAbsoluteExpiration(this CacheEntryOptions options, TimeSpan relative) { options.AbsoluteExpirationRelativeToNow = relative; return(options); }
public void Set(string key, byte[] data, CacheEntryOptions options = null) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } int[] callbacks = null; string[] dependencies = null; int slidingExpiration = 0; long absoluteExpiration = 0; var utcNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (options != null) { callbacks = new int[options.PostEvictionCallbacks.Count]; for (int i = 0; i < options.PostEvictionCallbacks.Count; i++) { var token = options.PostEvictionCallbacks[i].Method.MetadataToken; callbacks[i] = token; _entryLock.EnterUpgradeableReadLock(); if (!_delegates.ContainsKey(token)) { _entryLock.EnterWriteLock(); _delegates.Add(token, options.PostEvictionCallbacks[i]); _entryLock.ExitWriteLock(); } _entryLock.ExitUpgradeableReadLock(); } dependencies = new string[options.Dependencies.Count]; for (int i = 0; i < options.Dependencies.Count; i++) { dependencies[i] = options.Dependencies[i]; } } if (options.AbsoluteExpirationRelativeToNow.HasValue) { absoluteExpiration = utcNow + Convert.ToInt64(options.AbsoluteExpirationRelativeToNow.Value.TotalSeconds); } else if (options.AbsoluteExpiration.HasValue) { absoluteExpiration = options.AbsoluteExpiration.Value.ToUnixTimeSeconds(); } else if (options.SlidingExpiration.HasValue) { slidingExpiration = Convert.ToInt32(options.SlidingExpiration.Value.TotalSeconds); } CacheEntry entry = new CacheEntry(); entry.Key = key; entry.Data = data; entry.Dependencies = dependencies; using (var ms = new System.IO.MemoryStream()) { _wire.Serialize(callbacks, ms); entry.PostEvicationCallbacks = ms.ToArray(); } entry.LastAccessed = utcNow; entry.SlidingExpiration = slidingExpiration; entry.AbsoluteExpiration = absoluteExpiration; // Todo: // actually check if it should be added var added = true; // todo: // if we're not adding still run a "check and expire" operation instead CacheEntry existing = ReturnReadLockedOperation(() => { var cursor = _cursors.GetCursor(); cursor.MakeKey(entry.Key); lock (LockObject(cursor.GetNormalizedKey())) { try { CacheEntry previous = null; using (var transaction = cursor.BeginLazyTransaction()) { // If it exists, then ensure the channels are all subscribed // Do not throw an error if (cursor.TrySeek()) { // Get the basic details used in a callback, perhaps not the full // entry for performance, not sure yet previous = cursor.GetEntryForCallback(); cursor.Replace(entry); } // If it does not exist then add the row with all the columns // and then move on else { cursor.Insert(entry); } transaction.Commit(); } return(previous); } finally { _cursors.FreeCursor(cursor); } } }); if (existing != null && existing.PostEvicationCallbacks.Length > 0) { existing._EvictionReason = EvictionReason.Replaced; InvokeEvictionCallbacks(existing); } if (!added) { entry._EvictionReason = EvictionReason.Expired; InvokeEvictionCallbacks(entry); } StartScanForExpiredItems(); }
public void Set(long key, byte[] data, CacheEntryOptions options = null) { Set(key.ToString(), data, options); }