private bool RemoveInner(Delegate @delegate) { if (@delegate == null) { throw new ArgumentNullException("delegate"); } bool result; lock (this._SYNC) { CachedItem item = this.TryFindCachedItem(@delegate); if (item != null) { result = this._ITEMS.Remove(item); } else { result = false; } } return(result); }
public void When_appending_item_on_cache_will_append_to_data_already_on_cache() { var buffer = new byte[] { 1, 2, 3, 4 }; ICommand command = new SetCommand(); command.SetContext(GetStreamWithData(buffer)); command.Init("foo", "1", "6000", "4"); command.FinishedExecuting += () => { wait.Set(); }; command.Execute(); wait.WaitOne(); wait.Reset(); buffer = new byte[] { 5, 6, 7, 8 }; MemoryStream stream = GetStreamWithData(buffer); command = new AppendCommand(); command.SetContext(stream); command.Init("foo", "1", "6000", "4"); command.FinishedExecuting += () => { wait.Set(); }; command.Execute(); wait.WaitOne(); CachedItem item = (CachedItem)Cache.Get("foo"); CollectionAssert.AreEqual(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, item.Buffer); }
public void When_getting_item_that_is_in_cache_will_return_item() { Cache["foo"] = new CachedItem { Buffer = new byte[] { 1, 2, 3 }, Flags = 2, Key = "foo", ExpiresAt = SystemTime.Now().AddDays(1) }; var stream = new MemoryStream(); var command = new GetsCommand(); command.SetContext(stream); command.Init("foo"); command.FinishedExecuting += () => { wait.Set(); }; command.Execute(); wait.WaitOne(); stream.Position = 0; string line = new StreamReader(stream).ReadLine(); Assert.AreEqual("VALUE foo 2 3 630822816000000000", line); stream.Position = line.Length + 2; // reset buffering of stream reader var buffer = new byte[5]; stream.Read(buffer, 0, 5); CollectionAssert.AreEqual(new byte[] { 1, 2, 3, 13, 10 }, buffer); Assert.AreEqual("END", new StreamReader(stream).ReadLine()); }
async void AddLast_AddNewItemToEndOfEmptyList_ListContainsOnlyNewItem( [Frozen] Mock <Func <string, Task <ConditionalValue <CachedItem> > > > getCacheItem, ConditionalValue <CachedItem> cachedItem, CachedItem newCachedItem, LinkedDictionaryHelper linkedDictionaryHelper) { var cacheStoreMetadata = new CacheStoreMetadata(0, null, null); var newItemKey = "NewLastItem"; var cachedValue = Encoding.UTF8.GetBytes("some value"); var totalSize = cacheStoreMetadata.Size + cachedValue.Length; getCacheItem.Setup(mock => mock(It.IsAny <string>())).ReturnsAsync(await Task.FromResult(cachedItem)); var result = await linkedDictionaryHelper.AddLast(cacheStoreMetadata, newItemKey, newCachedItem, cachedValue); Assert.Equal(1, result.CachedItemsToUpdate.Count); var newLastItem = result.CachedItemsToUpdate[newItemKey]; Assert.Null(newLastItem.BeforeCacheKey); Assert.Null(newLastItem.AfterCacheKey); Assert.Equal(cachedValue, newLastItem.Value); Assert.Equal(newCachedItem.SlidingExpiration, newLastItem.SlidingExpiration); Assert.Equal(newCachedItem.AbsoluteExpiration, newLastItem.AbsoluteExpiration); Assert.Equal(totalSize, result.CacheStoreMetadata.Size); Assert.Equal(newItemKey, result.CacheStoreMetadata.FirstCacheKey); Assert.Equal(newItemKey, result.CacheStoreMetadata.LastCacheKey); }
/// <summary> /// Add a value to the cache /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="secondsToExpire">optional value for the seconds to expire</param> public void Add(TK key, TV value, int?secondsToExpire) { lock (_lockObject) { var cachedItem = new CachedItem(key, value, secondsToExpire ?? _secondsToExpire); cachedItem.Expired += delegate(TK cacheKey, TV cacheValue) { if (_internalCache.ContainsKey(cacheKey)) { Log.DebugFormat("Expiring object with Key: {0}", cacheKey); _expiredCallback?.Invoke(cacheKey, cacheValue); Remove(cacheKey); } else { Log.DebugFormat("Expired old object with Key: {0}", cacheKey); } }; if (_internalCache.ContainsKey(key)) { _internalCache[key] = value; Log.DebugFormat("Updated item with Key: {0}", key); } else { _internalCache.Add(key, cachedItem); Log.DebugFormat("Added item with Key: {0}", key); } } }
public void OnCacheRemoval(CachedItem cachedItem) { foreach (var eventHandler in _eventListeners) { eventHandler.OnCacheRemoval(cachedItem); } }
public void OnGetSuccessful(CachedItem cachedItem) { foreach (var eventListener in _eventListeners) { eventListener.OnGetSuccessful(cachedItem); } }
public void When_deleting_item_in_cache_with_time_will_block_cas_operations() { Cache["foo2"] = new CachedItem(); var stream = new MemoryStream(); var command = new DeleteCommand(); command.SetContext(stream); command.Init("foo2", "500"); command.FinishedExecuting += () => wait.Set(); command.Execute(); wait.WaitOne(); Assert.AreEqual("DELETED\r\n", ReadAll(stream)); wait.Reset(); var buffer = new byte[] { 1, 2, 3, 4 }; stream = GetStreamWithData(buffer); var casCommand = new CasCommand(); casCommand.SetContext(stream); casCommand.Init("foo2", "1", "6000", "4", "2"); casCommand.FinishedExecuting += () => wait.Set(); casCommand.Execute(); wait.WaitOne(); Assert.AreEqual("NOT_STORED\r\n", ReadAll(6, stream)); }
internal CachedItem Add(string key, TItem item) { Ensure.NotNull(key, $"{nameof(item)}.{key}"); lock (this.gate) // this was five times faster than ReaderWriterLockSlim in benchmarks. { var i = BinaryFind(this.cache, key); if (i >= 0) { var cachedItem = this.cache[i]; if (cachedItem.Key == key) { if (Equals(cachedItem.Value, item)) { return(cachedItem); } throw new InvalidOperationException("Cannot add same key with different values.\r\n" + $"The key is {key} and the values are {{{item}, {cachedItem.Value}}}"); } } var updated = new CachedItem[this.cache.Length + 1]; Array.Copy(this.cache, 0, updated, 0, this.cache.Length); var newItem = new CachedItem(key, item); updated[this.cache.Length] = newItem; Array.Sort(updated); this.cache = updated; return(newItem); } }
private List <TemplateMessage> GetTemplatesFromCache() { List <TemplateMessage> templates; CachedItem <List <TemplateMessage> > cached; if ((_CacheTemplates.TryGetValue(_CacheKeyTemplates, out cached))) { DateTime DataRead = DateTime.Now.AddMinutes(-15); if (cached == null || cached.InsertedDate < DataRead) { templates = GetTemplatesFromRepository(); _CacheTemplates[_CacheKeyTemplates] = new CachedItem <List <TemplateMessage> >(templates); } else { templates = cached.Item; } } else { templates = null; } return(templates); }
public void Add(TKey key, TValue value) { if (CacheStore <TKey, TValue> .s_cacheRepository == null) { throw new InvalidOperationException("You have not created a Cache Store yet."); } // LRU var convertedValue = new CachedItem <TValue> { Value = value, Lru = DateTime.Now }; if (CacheStore <TKey, TValue> .s_cacheRepository.Count == this._size) { this.c_evictionStrategy.Evict(CacheStore <TKey, TValue> .s_cacheRepository); } if (CacheStore <TKey, TValue> .s_cacheRepository.ContainsKey(key)) { CacheStore <TKey, TValue> .s_cacheRepository[key] = convertedValue; } else { CacheStore <TKey, TValue> .s_cacheRepository.Add(key, convertedValue); } }
public void SearchAsync_ShouldReturnCachedValueIfFresh() { Mock <ITransaction> tx = new Mock <ITransaction>(); Mock <IReliableDictionary <string, CachedItem <SearchOutput> > > cache = new Mock <IReliableDictionary <string, CachedItem <SearchOutput> > >(); CachedItem <SearchOutput> expectedResult = new CachedItem <SearchOutput> { Data = new SearchOutput { } }; cache.Setup(dict => dict.TryGetValueAsync(It.IsAny <ITransaction>(), It.IsAny <string>())) .Returns(Task.FromResult(new ConditionalValue <CachedItem <SearchOutput> >(true, expectedResult))); Mock <IGitHubClient> gitHubClient = new Mock <IGitHubClient>(); Result <SearchOutput> result = FullTextSearch.SearchAsync( input: new SearchInput { Query = "Test" }, cache: cache.Object, tx: tx.Object, gitHubClient: gitHubClient.Object).Result; Assert.True(result.Success); Assert.Equal(expectedResult.Data, result.Data); }
public void Add(string key, T item, TimeSpan slidingExpiration, DateTime absoluteExpiration) { lock (_lock) { var cachedItem = new CachedItem(key, item, slidingExpiration, absoluteExpiration, _time); if (_dic.TryGetValue(key, out var node)) { node.Value = cachedItem; Promote(key); return; } node = new LinkedListNode <CachedItem>(cachedItem); if (_dic.Count >= _cacheSize) { RemoveOldest(); } _keys.AddFirst(node); _dic[key] = node; } }
public static Func <T> Wrap <T>(TimeSpan maxAge, Func <T> inner) { var syncRoot = new object(); var item = default(CachedItem <T>); return(() => { var i = item; if (i == null || i.Watch.Elapsed > maxAge) { lock (syncRoot) { if (i == null || i.Watch.Elapsed > maxAge) { i = item = new CachedItem <T> { Value = inner(), Watch = Stopwatch.StartNew(), }; } } } return i.Value; }); }
/// <inheritdoc cref="IDistributedCache.SetAsync(string, byte[], DistributedCacheEntryOptions, CancellationToken)"/> public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default(CancellationToken)) { Guard.NotNullOrEmpty(key, nameof(key)); Guard.NotNullOrEmpty(value, nameof(value)); Guard.NotNull(options, nameof(options)); var currentTime = DateTimeOffset.UtcNow; var absoluteExpiration = ParseOptions(options, currentTime); var item = new CachedItem { PartitionKey = _options.PartitionKey, RowKey = key, Data = value, LastAccessTime = currentTime }; if (absoluteExpiration.HasValue) { item.AbsoluteExpiration = absoluteExpiration; } if (options.SlidingExpiration.HasValue) { item.SlidingExpiration = options.SlidingExpiration; } return(_tableSet.AddOrUpdateAsync(item, token)); }
public void OnCacheHit(CachedItem cachedItem) { foreach (var eventListener in _eventListeners) { eventListener.OnCacheHit(cachedItem); } }
private List <ErrorSettings> GetErrorSettingsFromCache() { List <ErrorSettings> settings; CachedItem <List <ErrorSettings> > cached; if ((_CacheErrorSettings.TryGetValue(_CacheKeyErrorSettings, out cached))) { DateTime DataRead = DateTime.Now.AddMinutes(-15); if (cached == null || cached.InsertedDate < DataRead) { GenericManager manager = new GenericManager(); settings = manager.GetErrorSettings(); _CacheErrorSettings[_CacheKeyErrorSettings] = new CachedItem <List <ErrorSettings> >(settings); } else { settings = cached.Item; } } else { settings = null; } return(settings); }
public void Adding_item_that_does_exists_on_cache_and_has_matching_timestamp_value_will_replace_value() { Cache["foo"] = new CachedItem { Buffer = new byte[] { 3, 4 }, Timestamp = 4 }; var stream = new MemoryStream(); stream.WriteByte(1); stream.WriteByte(2); stream.WriteByte(13); stream.WriteByte(10); stream.Position = 0; var command = new CasCommand(); command.SetContext(stream); command.Init("foo", "1", "0", "2", "4"); command.FinishedExecuting += () => wait.Set(); command.Execute(); wait.WaitOne(); var c = (CachedItem)Cache["foo"]; CollectionAssert.AreEqual(new byte[] { 1, 2 }, c.Buffer); Assert.IsTrue(4L != c.Timestamp); }
private List <MailTemplate> GetTemplatesFromCache() { List <MailTemplate> templates; CachedItem <List <MailTemplate> > cached; DateTime DataRead = DateTime.Now.AddMinutes(-15); if ((_CacheTemplates.TryGetValue(_CacheKeyMailTemplate, out cached))) { if (cached == null || cached.InsertedDate < DataRead) { GenericManager manager = new GenericManager(); templates = manager.GetTemplates(); _CacheTemplates[_CacheKeyMailTemplate] = new CachedItem <List <MailTemplate> >(templates); } else { templates = cached.Item; } } else { templates = null; } return(templates); }
public void When_Decrementing_value_on_cache_which_is_in_valid_format_use_this_as_base() { Cache["foo"] = new CachedItem { Buffer = Encoding.ASCII.GetBytes("12") }; var stream = new MemoryStream(); var command = new DecrCommand(); command.SetContext(stream); command.Init("foo", "5"); command.FinishedExecuting += () => { wait.Set(); }; command.Execute(); wait.WaitOne(); Assert.AreEqual("7\r\n", ReadAll(stream)); wait.Reset(); command.FinishedExecuting += () => { wait.Set(); }; command.Execute(); wait.WaitOne(); Assert.AreEqual("2\r\n", ReadAll(3, stream)); }
/// <summary> /// Add a value to the cache /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="secondsToExpire?">optional value for the seconds to expire</param> public void Add(TK key, TV value, int?secondsToExpire) { lock (lockObject) { var cachedItem = new CachedItem(key, value, secondsToExpire.HasValue ? secondsToExpire.Value : this.secondsToExpire); cachedItem.Expired += delegate(TK cacheKey, TV cacheValue) { if (internalCache.ContainsKey(cacheKey)) { LOG.DebugFormat("Expiring object with Key: {0}", cacheKey); if (expiredCallback != null) { expiredCallback(cacheKey, cacheValue); } Remove(cacheKey); } else { LOG.DebugFormat("Expired old object with Key: {0}", cacheKey); } }; if (internalCache.ContainsKey(key)) { internalCache[key] = value; LOG.DebugFormat("Updated item with Key: {0}", key); } else { internalCache.Add(key, cachedItem); LOG.DebugFormat("Added item with Key: {0}", key); } } }
private List <int> GetUsersByCommunityRolesFromCache(int CommunityID, int RoleID) { List <int> DestinationPersons; CachedItem <List <int> > cached; String Key = string.Format(_CacheKeyUserByCommunityRole, CommunityID, RoleID); if ((_CacheUsersRoles.TryGetValue(Key, out cached))) { DateTime DataRead = DateTime.Now.AddMinutes(-5); if (cached == null || cached.InsertedDate < DataRead) { DestinationPersons = CommunityService().GetCommunityRoleMembersID(CommunityID, RoleID).ToList <int>(); _CacheUsersRoles[Key] = new CachedItem <List <int> >(DestinationPersons); } else { DestinationPersons = cached.Item; } } else { DestinationPersons = null; } return(DestinationPersons); }
/// <summary> /// Set the first item in the linked list to the item provided. /// </summary> /// <param name="item"></param> internal void MoveFirst(CachedItem item) { if (item != First && item.IsValid == true) { lock (this) { if (item != First && item.IsValid == true) { if (item == Last) { // The item is the last one in the list so is // easy to remove. A new last will need to be // set. Last = item.Previous; Last.Next = null; } else { // The item was not at the end of the list. // Remove it from it's current position ready // to be added to the top of the list. item.Previous.Next = item.Next; item.Next.Previous = item.Previous; } // Add this item to the head of the linked list. item.Next = First; item.Previous = null; First.Previous = item; First = item; } } } }
List <int> GetUsersByCommunity(int CommunityID) { List <int> DestinationPersons; CachedItem <List <int> > cached; String Key = string.Format(_CacheKeyCommunity, CommunityID); DateTime DataRead = DateTime.Now.AddMinutes(-15); if ((_CacheUsers.TryGetValue(Key, out cached))) { if (cached == null || cached.InsertedDate < DataRead) { DestinationPersons = CommunityService().GetCommunityMembersID(CommunityID).ToList <int>(); _CacheUsers[Key] = new CachedItem <List <int> >(DestinationPersons); } else { DestinationPersons = cached.Item; } } else { DestinationPersons = CommunityService().GetCommunityMembersID(CommunityID).ToList <int>(); _CacheUsers.Add(Key, new CachedItem <List <int> >(DestinationPersons)); } return(DestinationPersons); }
public void OnPut(CachedItem cachedItem) { foreach (var eventHandler in _eventListeners) { eventHandler.OnPut(cachedItem); } }
public void OnCacheMiss(CachedItem cachedItem) { foreach (var eventHandler in _eventListeners) { eventHandler.OnCacheMiss(cachedItem); } }
/// <inheritdoc/> public override TItem Add(TItem item, bool replaceIfExists) { ArgumentValidator.EnsureArgumentNotNull(item, "item"); OnOperation2(); var key = KeyExtractor(item); CachedItem cached; if (items.TryGetValue(key, out cached)) { if (!replaceIfExists) { return(cached.Item); } if (chainedCache != null) { chainedCache.Add(cached.Item, true); } items.Remove(key); ItemRemoved(key); } cached = new CachedItem(item) { HitTime = time, HitCount = 1 }; items[key] = cached; ItemAdded(key); return(item); }
/// <summary> /// Stores or updates the value associated with the key. /// </summary> /// <param name="key">The key.</param> /// <param name="data">Stored value.</param> public static void Set(string key, T data) { if (String.IsNullOrEmpty(key)) { if (m_ignoreNullValues) { return; } throw new System.ArgumentNullException("key"); } if (data == null) { // remove data if data is null Remove(key); } else { // add or update item m_cacheMap[key] = new CachedItem { Updated = DateTime.UtcNow, Data = data }; // check if the timer is active StartMaintenance(); } }
List <int> GetUsersByPermission(int CommunityID, int ModuleID, int Permission) { List <int> DestinationPersons; String Key = string.Format(_CacheKeyPermission, CommunityID, ModuleID, Permission); DateTime DataRead = DateTime.Now.AddMinutes(-15); CachedItem <List <int> > cached; if ((_CacheUsers.TryGetValue(Key, out cached))) { if (cached == null || cached.InsertedDate < DataRead) { DestinationPersons = CommunityService().GetPermissionMembersID(CommunityID, ModuleID, Permission).ToList <int>(); _CacheUsers[Key] = new CachedItem <List <int> >(DestinationPersons); } else { DestinationPersons = cached.Item; } } else { DestinationPersons = CommunityService().GetPermissionMembersID(CommunityID, ModuleID, Permission).ToList <int>(); try { _CacheUsers.Add(Key, new CachedItem <List <int> >(DestinationPersons)); } catch (Exception ex) { _CacheUsers[Key] = new CachedItem <List <int> >(DestinationPersons); } } return(DestinationPersons); }
public async static Task <SearchOutput> GetSuggestionsAsync( IActorStateManager stateManager, SearchInput input) { IEnumerable <string> stateNames = await stateManager.GetStateNamesAsync(); stateNames = stateNames.Where(name => IsRepoScoreState(name)); List <SearchOutput.Item> items = new List <SearchOutput.Item>(); foreach (string name in stateNames) { CachedItem <RepositoryScore> scoreItem = await stateManager .GetStateAsync <CachedItem <RepositoryScore> >(name); items.Add(new SearchOutput.Item { Repository = scoreItem.Data.Repository, Score = ScoreCalculator.Calculate(scoreItem.Data) }); } items = items.OrderByDescending(item => item.Score) .Take(Constants.MAX_SUGGESTIONS).ToList(); return(new SearchOutput { Items = items }); }
public void With_timeout_will_set_expiry_in_cache() { var items = new List <CachedItem>(); for (int i = 0; i < 50; i++) { var cachedItem = new CachedItem { ExpiresAt = SystemTime.Now() }; items.Add(cachedItem); Cache[i.ToString()] = cachedItem; } Assert.AreEqual(50, Cache.Count); var stream = new MemoryStream(); var cmd = new FlushAllCommand(); cmd.SetContext(stream); cmd.Init("60"); cmd.FinishedExecuting += () => wait.Set(); cmd.Execute(); wait.WaitOne(); Assert.AreEqual(50, Cache.Count); foreach (var item in items) { Assert.AreEqual(new DateTime(2000, 1, 1, 0, 1, 0), item.ExpiresAt); } Assert.AreEqual("OK\r\n", ReadAll(stream)); }
public void SetUp() { var item1 = new CachedItem("apples-1", "Golden Delicious", DateTime.Now.AddHours(1)); var item2 = new CachedItem("apples-2", "Pink Lady", DateTime.Now.AddHours(1)); var item3 = new CachedItem("dogs-1", "Jack Russell", DateTime.Now.AddHours(1)); MongoCollection.Insert(item1); MongoCollection.Insert(item2); MongoCollection.Insert(item3); }
private object Deserialize(CachedItem item) { // Open memory stream MemoryStream mem = new MemoryStream(item.Value); try { // Deserialize value from memory BinaryFormatter formatter = new BinaryFormatter(); object value = formatter.Deserialize(mem); // Return return value; } finally { // Close memory stream mem.Close(); } }
void IEventListener.OnCacheHit(CachedItem cachedItem) { Interlocked.Increment(ref _cacheHits); }
private void RemoveNodeAndAdd(CachedItem item) { this.lock4Items.EnterWriteLock(); try { this.linkedList.Remove(item.Node); this.linkedList.AddFirst(item); item.Node = this.linkedList.First; } finally { this.lock4Items.ExitWriteLock(); } }
private CachedItem Serialize(object value, DateTime expires) { // Open memory stream MemoryStream mem = new MemoryStream(); try { // Serialize value to memory BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(mem,value); // Create cached item CachedItem item = new CachedItem(); item.Value = mem.ToArray(); item.Cached = DateTime.UtcNow; item.Expires = expires; // Return return item; } finally { // Close memory stream mem.Close(); } }
public InterlockedLinkedListNode AddFirst(CachedItem value) { InterlockedLinkedListNode newNode = new InterlockedLinkedListNode(this, value); if (this.head == null) { this.InternalInsertNodeToEmptyList(newNode); return newNode; } this.InternalInsertNodeBefore(this.head, newNode); this.head = newNode; return newNode; }
public CachedItemCallbackWrapper(CachedItem item, Func<object, object> callback, object callBackState, CacheDependency dependency, TimeSpan timeToLive, params string[] tags) { this.Item = item; this.Callback = callback; this.CallBackState = callBackState; this.Dependency = dependency; this.TTL = timeToLive; this.Tags = tags; }
//int failureCount = 0; //int failureCount2 = 0; private CachedItem LockedGetByCacheItem(CachedItem item, int millisecondsTimeout) { SpinWait wait = new SpinWait(); long startTicks = 0; if (millisecondsTimeout != -1 && millisecondsTimeout != 0) { startTicks = DateTime.UtcNow.Ticks; } do { if(Interlocked.CompareExchange(ref item.Node.item, InterlockedLinkedListNode.InvalidCachedItem, item) == item) { return item; } wait.SpinOnce(); } while (millisecondsTimeout != 0 && ((millisecondsTimeout == -1 || !wait.NextSpinWillYield) || !TimeoutExpired(startTicks, millisecondsTimeout))); //if (Interlocked.CompareExchange(ref failureCount, 0, 100) == 10) //{ // XMS.Core.Container.LogService.Debug(String.Format("为指定缓存项获取锁的等待时间超过 {0}ms 时间限制的次数超过 100 次的限制,为 {1} 次。", millisecondsTimeout, failureCount)); //} //Interlocked.Increment(ref failureCount); if (XMS.Core.Container.LogService.IsDebugEnabled) { XMS.Core.Container.LogService.Debug(String.Format("未能在指定的超时时间 {0}ms 内获取可用于提升当前命中缓存项位置的锁,缓存项的位置保持不变。", millisecondsTimeout)); } return null; }
/// <summary> /// 反向交换节点的值 /// </summary> public void ReverseExchange(CachedItem item) { if (item.Node == this.head) { return; } this.ValidateNode(item.Node); // 锁定超时时间暂定死为 1 毫秒,即 如果 1毫秒之内拿不到锁,则忽略本次调用 Thread.BeginCriticalRegion(); // 锁定当前缓存项及其节点 CachedItem current = LockedGetByCacheItem(item, 1); // 判断是否锁定成功: current == null 说明在上述给定超时时间内没有锁定成功,忽略本次交换 if (current != null) { // 锁定当前缓存项对应节点的前一节点 CachedItem previous = LockedGetByNode(item.Node.prev, 1); // 判断是否锁定成功: current == null 说明在上述给定超时时间内没有锁定成功,忽略本次交换 if (previous != null) { // 锁定成功,交换当前命中缓存项和其前一缓存项对应节点的值,不改变链表节点的结构 previous.Node = item.Node; current.Node = item.Node.prev; // 先解锁后锁定的节点 current.Node.item = current; // 然后解锁先锁定的节点 previous.Node.item = previous; } else { // 解锁锁定的节点 current.Node.item = current; } } Thread.EndCriticalRegion(); }
private void SetItemInternal(string key, object value, CacheDependency dependency, TimeSpan timeToLive, DateTime? nextUpdateTime, params string[] tags) { if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullOrWhiteSpaceException("key"); } if (value == null) { throw new ArgumentNullException("value"); } CachedItem item = new CachedItem(); if (tags != null && tags.Length > 0) { EnsureTags(tags); item.Tags = tags; } item.Key = key; item.Value = value; item.ExpiredTime = timeToLive.Days > 1000 ? DateTime.Now.AddDays(1000) : DateTime.Now + timeToLive; item.NextUpdateTime = nextUpdateTime; item.Dependency = dependency; // 优化实现: 使用读写锁,减少高并发读取阻塞 this.lock4Items.EnterWriteLock(); try { // 覆盖时处理旧项 if (this.cachedItems.ContainsKey(key)) { this.RemoveItemInternal(key); } #region LRU 支持 if (this.cachedItems.Count >= this.capacity) { this.RemoveItemInternal(this.linkedList.Last.item.Key); } #endregion this.cachedItems.Add(key, item); #region LRU 支持,新添加的设为第一个 this.linkedList.AddFirst(item); item.Node = this.linkedList.First; #endregion if (tags != null && tags.Length > 0) { foreach (string tag in tags) { if (!this.cachedItemKeyByTags.ContainsKey(tag)) { this.cachedItemKeyByTags.Add(tag, new Dictionary<string, KeyValuePair<string, CachedItem>>(StringComparer.InvariantCultureIgnoreCase)); } Dictionary<string, KeyValuePair<string, CachedItem>> keys = this.cachedItemKeyByTags[tag]; if (!this.cachedItemObjectByTags.ContainsKey(tag)) { this.cachedItemObjectByTags.Add(tag, new List<KeyValuePair<string, CachedItem>>()); } List<KeyValuePair<string, CachedItem>> objects = this.cachedItemObjectByTags[tag]; KeyValuePair<string, CachedItem> newKvp = new KeyValuePair<string, CachedItem>(key, item); int index; if (keys.ContainsKey(key) && ((index = objects.IndexOf(keys[key])) >= 0)) // 覆盖时 { objects[index] = newKvp; } else { objects.Add(newKvp); } keys[key] = newKvp; } } } finally { this.lock4Items.ExitWriteLock(); } }
internal InterlockedLinkedListNode(InterlockedLinkedList list, CachedItem value) { this.list = list; this.item = value; }
public CachedItemCallbackWrapper(CachedItem item, Func<object, object> callback, object callBackState, CacheDependency dependency, int timeToLiveInSeconds, params string[] tags) { this.Item = item; this.Callback = callback; this.CallBackState = callBackState; this.Dependency = dependency; this.TTL = TimeSpan.FromSeconds(timeToLiveInSeconds); this.Tags = tags; }
void IEventListener.OnCacheRemoval(CachedItem cachedItem) { }
public IIssue GetIssue(string key) { IIssue issue; if (cache.ContainsKey(key)) { CachedItem item = cache[key]; if ((DateTime.Now - item.TimeCached) > this.cacheExpiryPeriod) { issue = this.GetIssueFromService(key); cache[key] = new CachedItem(issue); return issue; } return cache[key].Issue; } issue = this.GetIssueFromService(key); cache.Add(key, new CachedItem(issue)); return issue; }