private bool SetInternal(CacheEntry entry, bool addOnly = false) { if (entry.ExpiresAt < SystemClock.UtcNow) { RemoveExpiredKey(entry.Key); return(false); } if (_memory.Count >= _options.SizeLimit) { // order by last access ticks // up to size limit, should remove var oldestList = _memory.ToArray() .OrderBy(kvp => kvp.Value.LastAccessTicks) .ThenBy(kvp => kvp.Value.InstanceNumber) .Take(5) .Select(kvp => kvp.Key); RemoveAll(oldestList); } CacheEntry deep = null; if (_options.EnableWriteDeepClone) { try { deep = DeepClonerGenerator.CloneObject(entry); } catch (Exception) { deep = entry; } } else { deep = entry; } if (addOnly) { if (!_memory.TryAdd(deep.Key, deep)) { if (!_memory.TryGetValue(deep.Key, out var existingEntry) || existingEntry.ExpiresAt >= SystemClock.UtcNow) { return(false); } _memory.AddOrUpdate(deep.Key, deep, (k, cacheEntry) => deep); } } else { _memory.AddOrUpdate(deep.Key, deep, (k, cacheEntry) => deep); } StartScanForExpiredItems(); return(true); }
/// <summary> /// conver to T /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public T GetValue <T>(bool isDeepClone = true) { object val = Value; var t = typeof(T); if (t == TypeHelper.BoolType || t == TypeHelper.StringType || t == TypeHelper.CharType || t == TypeHelper.DateTimeType || t.IsNumeric()) { return((T)Convert.ChangeType(val, t)); } if (t == TypeHelper.NullableBoolType || t == TypeHelper.NullableCharType || t == TypeHelper.NullableDateTimeType || t.IsNullableNumeric()) { return(val == null ? default(T) : (T)Convert.ChangeType(val, Nullable.GetUnderlyingType(t))); } return(isDeepClone ? DeepClonerGenerator.CloneObject <T>((T)val) : (T)val); }
private bool SetInternal(CacheEntry entry, bool addOnly = false) { if (entry.ExpiresAt < SystemClock.UtcNow) { RemoveExpiredKey(entry.Key); return(false); } if (_options.SizeLimit.HasValue && Interlocked.Read(ref _cacheSize) >= _options.SizeLimit) { // prevent alaways access the following logic after up to limit if (_memory.TryAdd(_UPTOLIMIT_KEY, new CacheEntry(_UPTOLIMIT_KEY, 1, DateTimeOffset.UtcNow.AddSeconds(5)))) { var shouldRemoveCount = 5; if (_options.SizeLimit.Value >= 10000) { shouldRemoveCount = (int)(_options.SizeLimit * 0.005d); } else if (_options.SizeLimit.Value >= 1000 && _options.SizeLimit.Value < 10000) { shouldRemoveCount = (int)(_options.SizeLimit * 0.01d); } var oldestList = _memory.ToArray() .OrderBy(kvp => kvp.Value.LastAccessTicks) .ThenBy(kvp => kvp.Value.InstanceNumber) .Take(shouldRemoveCount) .Select(kvp => kvp.Key); RemoveAll(oldestList); //// this key will be remove by ScanForExpiredItems. //_memory.TryRemove(_UPTOLIMIT_KEY, out _); } } CacheEntry deep = null; if (_options.EnableWriteDeepClone) { try { deep = DeepClonerGenerator.CloneObject(entry); } catch (Exception) { deep = entry; } } else { deep = entry; } if (addOnly) { if (!_memory.TryAdd(deep.Key, deep)) { if (!_memory.TryGetValue(deep.Key, out var existingEntry) || existingEntry.ExpiresAt >= SystemClock.UtcNow) { return(false); } _memory.AddOrUpdate(deep.Key, deep, (k, cacheEntry) => deep); if (_options.SizeLimit.HasValue) { Interlocked.Increment(ref _cacheSize); } } } else { _memory.AddOrUpdate(deep.Key, deep, (k, cacheEntry) => deep); if (_options.SizeLimit.HasValue) { Interlocked.Increment(ref _cacheSize); } } StartScanForExpiredItems(); return(true); }