public bool TryGet(string key, out CacheEntry data) { throw new NotImplementedException(); }
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(); }