You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,14 @@
|
||||
// <copyright file="CacheEntryChangeMonitor.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public abstract class CacheEntryChangeMonitor : ChangeMonitor {
|
||||
public abstract ReadOnlyCollection<string> CacheKeys { get; }
|
||||
public abstract DateTimeOffset LastModified { get; }
|
||||
public abstract String RegionName { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
// <copyright file="CacheEntryRemovedArguments.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public class CacheEntryRemovedArguments {
|
||||
private CacheItem _cacheItem;
|
||||
private ObjectCache _source;
|
||||
private CacheEntryRemovedReason _reason;
|
||||
|
||||
public CacheItem CacheItem {
|
||||
get { return _cacheItem; }
|
||||
}
|
||||
|
||||
public CacheEntryRemovedReason RemovedReason {
|
||||
get { return _reason; }
|
||||
}
|
||||
|
||||
public ObjectCache Source {
|
||||
get { return _source; }
|
||||
}
|
||||
|
||||
public CacheEntryRemovedArguments(ObjectCache source, CacheEntryRemovedReason reason, CacheItem cacheItem) {
|
||||
if (source == null) {
|
||||
throw new ArgumentNullException("source");
|
||||
}
|
||||
if (cacheItem == null) {
|
||||
throw new ArgumentNullException("cacheItem");
|
||||
}
|
||||
_source = source;
|
||||
_reason = reason;
|
||||
_cacheItem = cacheItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,8 @@
|
||||
// <copyright file="CacheEntryUpdateRemoved.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public delegate void CacheEntryRemovedCallback(CacheEntryRemovedArguments arguments);
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
// <copyright file="CacheEntryRemovedReason.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public enum CacheEntryRemovedReason {
|
||||
Removed = 0, //Explicitly removed via API call
|
||||
Expired,
|
||||
Evicted, //Evicted to free up space
|
||||
ChangeMonitorChanged, //An associated programmatic dependency triggered eviction
|
||||
CacheSpecificEviction //Catch-all for custom providers
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
// <copyright file="CacheEntryUpdateArguments.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public class CacheEntryUpdateArguments {
|
||||
private String _key;
|
||||
private CacheEntryRemovedReason _reason;
|
||||
private String _regionName;
|
||||
private ObjectCache _source;
|
||||
private CacheItem _updatedCacheItem;
|
||||
private CacheItemPolicy _updatedCacheItemPolicy;
|
||||
|
||||
public String Key {
|
||||
get { return _key; }
|
||||
}
|
||||
|
||||
public CacheEntryRemovedReason RemovedReason {
|
||||
get { return _reason; }
|
||||
}
|
||||
|
||||
public String RegionName {
|
||||
get { return _regionName; }
|
||||
}
|
||||
|
||||
public ObjectCache Source {
|
||||
get { return _source; }
|
||||
}
|
||||
|
||||
public CacheItem UpdatedCacheItem {
|
||||
get { return _updatedCacheItem; }
|
||||
set { _updatedCacheItem = value; }
|
||||
}
|
||||
|
||||
public CacheItemPolicy UpdatedCacheItemPolicy {
|
||||
get { return _updatedCacheItemPolicy; }
|
||||
set { _updatedCacheItemPolicy = value; }
|
||||
}
|
||||
|
||||
public CacheEntryUpdateArguments(ObjectCache source, CacheEntryRemovedReason reason, String key, String regionName) {
|
||||
if (source == null) {
|
||||
throw new ArgumentNullException("source");
|
||||
}
|
||||
if (key == null) {
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
_source = source;
|
||||
_reason = reason;
|
||||
_key = key;
|
||||
_regionName = regionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,8 @@
|
||||
// <copyright file="CacheEntryUpdateCallback.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public delegate void CacheEntryUpdateCallback(CacheEntryUpdateArguments arguments);
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
// <copyright file="CacheItem.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public class CacheItem {
|
||||
public string Key { get; set; }
|
||||
public object Value { get; set; }
|
||||
public string RegionName { get; set; }
|
||||
|
||||
private CacheItem() { } // hide default constructor
|
||||
|
||||
public CacheItem(string key) {
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public CacheItem(string key, object value) : this(key) {
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public CacheItem(string key, object value, string regionName) : this(key, value) {
|
||||
RegionName = regionName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,56 @@
|
||||
// <copyright file="CacheItemPolicy.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public class CacheItemPolicy {
|
||||
private DateTimeOffset _absExpiry;
|
||||
private TimeSpan _sldExpiry;
|
||||
private Collection<ChangeMonitor> _changeMonitors;
|
||||
private CacheItemPriority _priority;
|
||||
private CacheEntryRemovedCallback _removedCallback;
|
||||
private CacheEntryUpdateCallback _updateCallback;
|
||||
|
||||
public DateTimeOffset AbsoluteExpiration {
|
||||
get { return _absExpiry; }
|
||||
set { _absExpiry = value; }
|
||||
}
|
||||
|
||||
public Collection<ChangeMonitor> ChangeMonitors {
|
||||
get {
|
||||
if (_changeMonitors == null) {
|
||||
_changeMonitors = new Collection<ChangeMonitor>();
|
||||
}
|
||||
return _changeMonitors;
|
||||
}
|
||||
}
|
||||
|
||||
public CacheItemPriority Priority {
|
||||
get { return _priority; }
|
||||
set { _priority = value; }
|
||||
}
|
||||
|
||||
public CacheEntryRemovedCallback RemovedCallback {
|
||||
get { return _removedCallback; }
|
||||
set { _removedCallback = value; }
|
||||
}
|
||||
|
||||
public TimeSpan SlidingExpiration {
|
||||
get { return _sldExpiry; }
|
||||
set { _sldExpiry = value; }
|
||||
}
|
||||
|
||||
public CacheEntryUpdateCallback UpdateCallback {
|
||||
get { return _updateCallback; }
|
||||
set { _updateCallback = value; }
|
||||
}
|
||||
|
||||
public CacheItemPolicy() {
|
||||
_absExpiry = ObjectCache.InfiniteAbsoluteExpiration;
|
||||
_sldExpiry = ObjectCache.NoSlidingExpiration;
|
||||
_priority = CacheItemPriority.Default;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
// <copyright file="CacheItemPriority.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public enum CacheItemPriority {
|
||||
Default = 0,
|
||||
NotRemovable
|
||||
}
|
||||
}
|
@@ -0,0 +1,259 @@
|
||||
// <copyright file="CacheMemoryMonitor.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Runtime.Caching.Configuration;
|
||||
using System.Runtime.Caching.Hosting;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
// CacheMemoryMonitor uses the internal System.SizedReference type to determine
|
||||
// the size of the cache itselt, and helps us know when to drop entries to avoid
|
||||
// exceeding the cache's memory limit. The limit is configurable (see ConfigUtil.cs).
|
||||
internal sealed class CacheMemoryMonitor : MemoryMonitor, IDisposable {
|
||||
const long PRIVATE_BYTES_LIMIT_2GB = 800 * MEGABYTE;
|
||||
const long PRIVATE_BYTES_LIMIT_3GB = 1800 * MEGABYTE;
|
||||
const long PRIVATE_BYTES_LIMIT_64BIT = 1L * TERABYTE;
|
||||
const int SAMPLE_COUNT = 2;
|
||||
|
||||
private static IMemoryCacheManager s_memoryCacheManager;
|
||||
private static long s_autoPrivateBytesLimit = -1;
|
||||
private static long s_effectiveProcessMemoryLimit = -1;
|
||||
|
||||
private MemoryCache _memoryCache;
|
||||
private long[] _cacheSizeSamples;
|
||||
private DateTime[] _cacheSizeSampleTimes;
|
||||
private int _idx;
|
||||
private SRef _sizedRef;
|
||||
private int _gen2Count;
|
||||
private long _memoryLimit;
|
||||
|
||||
internal long MemoryLimit {
|
||||
get { return _memoryLimit; }
|
||||
}
|
||||
|
||||
private CacheMemoryMonitor() {
|
||||
// hide default ctor
|
||||
}
|
||||
|
||||
internal CacheMemoryMonitor(MemoryCache memoryCache, int cacheMemoryLimitMegabytes) {
|
||||
_memoryCache = memoryCache;
|
||||
_gen2Count = GC.CollectionCount(2);
|
||||
_cacheSizeSamples = new long[SAMPLE_COUNT];
|
||||
_cacheSizeSampleTimes = new DateTime[SAMPLE_COUNT];
|
||||
InitMemoryCacheManager();
|
||||
InitDisposableMembers(cacheMemoryLimitMegabytes);
|
||||
}
|
||||
|
||||
private void InitDisposableMembers(int cacheMemoryLimitMegabytes) {
|
||||
bool dispose = true;
|
||||
try {
|
||||
_sizedRef = new SRef(_memoryCache);
|
||||
SetLimit(cacheMemoryLimitMegabytes);
|
||||
InitHistory();
|
||||
dispose = false;
|
||||
}
|
||||
finally {
|
||||
if (dispose) {
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-generate the private bytes limit:
|
||||
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
|
||||
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
|
||||
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
|
||||
//
|
||||
// - If it's not a hosted environment (e.g. console app), the 60% in the above
|
||||
// formulas will become 100% because in un-hosted environment we don't launch
|
||||
// other processes such as compiler, etc.
|
||||
private static long AutoPrivateBytesLimit {
|
||||
get {
|
||||
long memoryLimit = s_autoPrivateBytesLimit;
|
||||
if (memoryLimit == -1) {
|
||||
|
||||
bool is64bit = (IntPtr.Size == 8);
|
||||
|
||||
long totalPhysical = TotalPhysical;
|
||||
long totalVirtual = TotalVirtual;
|
||||
if (totalPhysical != 0) {
|
||||
long recommendedPrivateByteLimit;
|
||||
if (is64bit) {
|
||||
recommendedPrivateByteLimit = PRIVATE_BYTES_LIMIT_64BIT;
|
||||
}
|
||||
else {
|
||||
// Figure out if it's 2GB or 3GB
|
||||
|
||||
if (totalVirtual > 2 * GIGABYTE) {
|
||||
recommendedPrivateByteLimit = PRIVATE_BYTES_LIMIT_3GB;
|
||||
}
|
||||
else {
|
||||
recommendedPrivateByteLimit = PRIVATE_BYTES_LIMIT_2GB;
|
||||
}
|
||||
}
|
||||
|
||||
// use 60% of physical RAM
|
||||
long usableMemory = totalPhysical * 3 / 5;
|
||||
memoryLimit = Math.Min(usableMemory, recommendedPrivateByteLimit);
|
||||
}
|
||||
else {
|
||||
// If GlobalMemoryStatusEx fails, we'll use these as our auto-gen private bytes limit
|
||||
memoryLimit = is64bit ? PRIVATE_BYTES_LIMIT_64BIT : PRIVATE_BYTES_LIMIT_2GB;
|
||||
}
|
||||
Interlocked.Exchange(ref s_autoPrivateBytesLimit, memoryLimit);
|
||||
}
|
||||
|
||||
return memoryLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
SRef sref = _sizedRef;
|
||||
if (sref != null && Interlocked.CompareExchange(ref _sizedRef, null, sref) == sref) {
|
||||
sref.Dispose();
|
||||
}
|
||||
IMemoryCacheManager memoryCacheManager = s_memoryCacheManager;
|
||||
if (memoryCacheManager != null) {
|
||||
memoryCacheManager.ReleaseCache(_memoryCache);
|
||||
}
|
||||
}
|
||||
|
||||
internal static long EffectiveProcessMemoryLimit {
|
||||
get {
|
||||
long memoryLimit = s_effectiveProcessMemoryLimit;
|
||||
if (memoryLimit == -1) {
|
||||
memoryLimit = AutoPrivateBytesLimit;
|
||||
Interlocked.Exchange(ref s_effectiveProcessMemoryLimit, memoryLimit);
|
||||
}
|
||||
return memoryLimit;
|
||||
}
|
||||
}
|
||||
|
||||
protected override int GetCurrentPressure() {
|
||||
// Call GetUpdatedTotalCacheSize to update the total
|
||||
// cache size, if there has been a recent Gen 2 Collection.
|
||||
// This update must happen, otherwise the CacheManager won't
|
||||
// know the total cache size.
|
||||
int gen2Count = GC.CollectionCount(2);
|
||||
SRef sref = _sizedRef;
|
||||
if (gen2Count != _gen2Count && sref != null) {
|
||||
// update _gen2Count
|
||||
_gen2Count = gen2Count;
|
||||
|
||||
// the SizedRef is only updated after a Gen2 Collection
|
||||
|
||||
// increment the index (it's either 1 or 0)
|
||||
Dbg.Assert(SAMPLE_COUNT == 2);
|
||||
_idx = _idx ^ 1;
|
||||
// remember the sample time
|
||||
_cacheSizeSampleTimes[_idx] = DateTime.UtcNow;
|
||||
// remember the sample value
|
||||
_cacheSizeSamples[_idx] = sref.ApproximateSize;
|
||||
#if DBG
|
||||
Dbg.Trace("MemoryCacheStats", "SizedRef.ApproximateSize=" + _cacheSizeSamples[_idx]);
|
||||
#endif
|
||||
IMemoryCacheManager memoryCacheManager = s_memoryCacheManager;
|
||||
if (memoryCacheManager != null) {
|
||||
memoryCacheManager.UpdateCacheSize(_cacheSizeSamples[_idx], _memoryCache);
|
||||
}
|
||||
}
|
||||
|
||||
// if there's no memory limit, then there's nothing more to do
|
||||
if (_memoryLimit <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long cacheSize = _cacheSizeSamples[_idx];
|
||||
|
||||
// use _memoryLimit as an upper bound so that pressure is a percentage (between 0 and 100, inclusive).
|
||||
if (cacheSize > _memoryLimit) {
|
||||
cacheSize = _memoryLimit;
|
||||
}
|
||||
|
||||
// PerfCounter: Cache Percentage Process Memory Limit Used
|
||||
// = memory used by this process / process memory limit at pressureHigh
|
||||
// Set private bytes used in kilobytes because the counter is a DWORD
|
||||
|
||||
//
|
||||
|
||||
|
||||
int result = (int)(cacheSize * 100 / _memoryLimit);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override int GetPercentToTrim(DateTime lastTrimTime, int lastTrimPercent) {
|
||||
int percent = 0;
|
||||
if (IsAboveHighPressure()) {
|
||||
long cacheSize = _cacheSizeSamples[_idx];
|
||||
if (cacheSize > _memoryLimit) {
|
||||
percent = Math.Min(100, (int)((cacheSize - _memoryLimit) * 100L / cacheSize));
|
||||
}
|
||||
|
||||
#if PERF
|
||||
SafeNativeMethods.OutputDebugString(String.Format("CacheMemoryMonitor.GetPercentToTrim: percent={0:N}, lastTrimPercent={1:N}\n",
|
||||
percent,
|
||||
lastTrimPercent));
|
||||
#endif
|
||||
|
||||
}
|
||||
return percent;
|
||||
}
|
||||
|
||||
internal void SetLimit(int cacheMemoryLimitMegabytes) {
|
||||
long cacheMemoryLimit = cacheMemoryLimitMegabytes;
|
||||
cacheMemoryLimit = cacheMemoryLimit << MEGABYTE_SHIFT;
|
||||
|
||||
//
|
||||
_memoryLimit = 0;
|
||||
|
||||
// VSWhidbey 546381: never override what the user specifies as the limit;
|
||||
// only call AutoPrivateBytesLimit when the user does not specify one.
|
||||
if (cacheMemoryLimit == 0 && _memoryLimit == 0) {
|
||||
// Zero means we impose a limit
|
||||
_memoryLimit = EffectiveProcessMemoryLimit;
|
||||
}
|
||||
else if (cacheMemoryLimit != 0 && _memoryLimit != 0) {
|
||||
// Take the min of "cache memory limit" and the host's "process memory limit".
|
||||
_memoryLimit = Math.Min(_memoryLimit, cacheMemoryLimit);
|
||||
}
|
||||
else if (cacheMemoryLimit != 0) {
|
||||
// _memoryLimit is 0, but "cache memory limit" is non-zero, so use it as the limit
|
||||
_memoryLimit = cacheMemoryLimit;
|
||||
}
|
||||
|
||||
Dbg.Trace("MemoryCacheStats", "CacheMemoryMonitor.SetLimit: _memoryLimit=" + (_memoryLimit >> MEGABYTE_SHIFT) + "Mb");
|
||||
|
||||
if (_memoryLimit > 0) {
|
||||
_pressureHigh = 100;
|
||||
_pressureLow = 80;
|
||||
}
|
||||
else {
|
||||
_pressureHigh = 99;
|
||||
_pressureLow = 97;
|
||||
}
|
||||
|
||||
Dbg.Trace("MemoryCacheStats", "CacheMemoryMonitor.SetLimit: _pressureHigh=" + _pressureHigh +
|
||||
", _pressureLow=" + _pressureLow);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
|
||||
[SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "Grandfathered suppression from original caching code checkin")]
|
||||
private static void InitMemoryCacheManager() {
|
||||
if (s_memoryCacheManager == null) {
|
||||
IMemoryCacheManager memoryCacheManager = null;
|
||||
IServiceProvider host = ObjectCache.Host;
|
||||
if (host != null) {
|
||||
memoryCacheManager = host.GetService(typeof(IMemoryCacheManager)) as IMemoryCacheManager;
|
||||
}
|
||||
if (memoryCacheManager != null) {
|
||||
Interlocked.CompareExchange(ref s_memoryCacheManager, memoryCacheManager, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,225 @@
|
||||
// <copyright file="ChangeMonitor.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Runtime.Caching.Resources;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
|
||||
// Every member of this class is thread-safe.
|
||||
//
|
||||
// Derived classes begin monitoring during construction, so that a user can know if the
|
||||
// dependency changed any time after construction. For example, suppose we have a
|
||||
// FileChangeMonitor class that derives from ChangeMonitor. A user might create an instance
|
||||
// of FileChangeMonitor for an XML file, and then read the file to populate an object representation.
|
||||
// The user would then cache the object with the FileChangeMonitor. The user could optionally check the
|
||||
// HasChanged property of the FileChangeMonitor, to see if the XML file changed while the object
|
||||
// was being populated, and if it had changed, they could call Dispose and start over, without
|
||||
// inserting the item into the cache. However, in a multi-threaded environment, for cleaner, easier
|
||||
// to maintain code, it's usually appropriate to just insert without checking HasChanged, since the
|
||||
// cache implementer will handle this for you, and the next thread to attempt to get the object
|
||||
// will recreate and insert it.
|
||||
//
|
||||
// The following contract must be followed by derived classes, cache implementers, and users of the
|
||||
// derived class:
|
||||
//
|
||||
// 1. The constructor of a derived class must set UniqueId, begin monitoring for dependency
|
||||
// changes, and call InitializationComplete before returning. If a dependency changes
|
||||
// before initialization is complete, for example, if a dependent cache key is not found
|
||||
// in the cache, the constructor must invoke OnChanged. The constructor can only call
|
||||
// Dispose after InitializationComplete is called, because Dispose will throw
|
||||
// InvalidOperationException if initialization is not complete.
|
||||
// 2. Once constructed, the user must either insert the ChangeMonitor into an ObjectCache, or
|
||||
// if they're not going to use it, they must call Dispose.
|
||||
// 3. Once inserted into an ObjectCache, the ObjectCache implementation must ensure that the
|
||||
// ChangeMonitor is eventually disposed. Even if the insert is invalid, and results in an
|
||||
// exception being thrown, the ObjectCache implementation must call Dispose. If this we're not
|
||||
// a requirement, users of the ChangeMonitor would need exception handling around each insert
|
||||
// into the cache that carefully ensures the dependency is disposed. While this would work, we
|
||||
// think it is better to put this burden on the ObjectCache implementer, since users are far more
|
||||
// numerous than cache implementers.
|
||||
// 4. After the ChangeMonitor is inserted into a cache, the ObjectCache implementer must call
|
||||
// NotifyOnChanged, passing in an OnChangedCallback. NotifyOnChanged can only be called once,
|
||||
// and will throw InvalidOperationException on subsequent calls. If the dependency has already
|
||||
// changed, the OnChangedCallback will be called when NotifyOnChanged is called. Otherwise, the
|
||||
// OnChangedCallback will be called exactly once, when OnChanged is invoked or when Dispose
|
||||
// is invoked, which ever happens first.
|
||||
// 5. The OnChangedCallback provided by the cache implementer should remove the cache entry, and specify
|
||||
// a reason of CacheEntryRemovedReason.DependencyChanged. Care should be taken to remove the specific
|
||||
// entry having this dependency, and not it's replacement, which will have the same key.
|
||||
// 6. In general, it is okay for OnChanged to be called at any time. If OnChanged is called before
|
||||
// NotifyOnChanged is called, the "state" from the original call to OnChanged will be saved, and the
|
||||
// callback to NotifyOnChange will be called immediately when NotifyOnChanged is invoked.
|
||||
// 7. A derived class must implement Dispose(bool disposing) to release all managed and unmanaged
|
||||
// resources when "disposing" is true. Dispose(true) is only called once, when the instance is
|
||||
// disposed. The derived class must not call Dispose(true) directly--it should only be called by
|
||||
// the ChangeMonitor class, when disposed. Although a derived class could implement a finalizer and
|
||||
// invoke Dispose(false), this is generally not necessary. Dependency monitoring is typically performed
|
||||
// by a service that maintains a reference to the ChangeMonitor, preventing it from being garbage collected,
|
||||
// and making finalizers useless. To help prevent leaks, when a dependency changes, OnChanged disposes
|
||||
// the ChangeMonitor, unless initialization has not yet completed.
|
||||
// 8. Dispose() must be called, and is designed to be called, in one of the following three ways:
|
||||
// - The user must call Dispose() if they decide not to insert the ChangeMonitor into a cache. Otherwise,
|
||||
// the ChangeMonitor will continue monitoring for changes and be unavailable for garbage collection.
|
||||
// - The cache implementor is responsible for calling Dispose() once an attempt is made to insert it.
|
||||
// Even if the insert throws, the cache implementor must dispose the dependency.
|
||||
// Even if the entry is removed, the cache implementor must dispose the dependency.
|
||||
// - The OnChanged method will automatically call Dispose if initialization is complete. Otherwise, when
|
||||
// the derived class' constructor calls InitializationComplete, the instance will be automatically disposed.
|
||||
//
|
||||
// Before inserted into the cache, the user must ensure the dependency is disposed. Once inserted into the
|
||||
// cache, the cache implementer must ensure that Dispose is called, even if the insert fails. After being inserted
|
||||
// into a cache, the user should not dispose the dependency. When Dispose is called, it is treated as if the dependency
|
||||
// changed, and OnChanged is automatically invoked.
|
||||
// 9. HasChanged will be true after OnChanged is called by the derived class, regardless of whether an OnChangedCallback has been set
|
||||
// by a call to NotifyOnChanged.
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public abstract class ChangeMonitor : IDisposable {
|
||||
private const int INITIALIZED = 0x01; // initialization complete
|
||||
private const int CHANGED = 0x02; // dependency changed
|
||||
private const int INVOKED = 0x04; // OnChangedCallback has been invoked
|
||||
private const int DISPOSED = 0x08; // Dispose(true) called, or about to be called
|
||||
private readonly static object NOT_SET = new object();
|
||||
|
||||
private SafeBitVector32 _flags;
|
||||
private OnChangedCallback _onChangedCallback;
|
||||
private Object _onChangedState = NOT_SET;
|
||||
|
||||
// The helper routines (OnChangedHelper and DisposeHelper) are used to prevent
|
||||
// an infinite loop, where Dispose calls OnChanged and OnChanged calls Dispose.
|
||||
[SuppressMessage("Microsoft.Performance", "CA1816:DisposeMethodsShouldCallSuppressFinalize", Justification = "Grandfathered suppression from original caching code checkin")]
|
||||
private void DisposeHelper() {
|
||||
// if not initialized, return without doing anything.
|
||||
if (_flags[INITIALIZED]) {
|
||||
if (_flags.ChangeValue(DISPOSED, true)) {
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The helper routines (OnChangedHelper and DisposeHelper) are used to prevent
|
||||
// an infinite loop, where Dispose calls OnChanged and OnChanged calls Dispose.
|
||||
private void OnChangedHelper(Object state) {
|
||||
_flags[CHANGED] = true;
|
||||
|
||||
// the callback is only invoked once, after NotifyOnChanged is called, so
|
||||
// remember "state" on the first call and use it when invoking the callback
|
||||
Interlocked.CompareExchange(ref _onChangedState, state, NOT_SET);
|
||||
|
||||
OnChangedCallback onChangedCallback = _onChangedCallback;
|
||||
if (onChangedCallback != null) {
|
||||
// only invoke the callback once
|
||||
if (_flags.ChangeValue(INVOKED, true)) {
|
||||
onChangedCallback(_onChangedState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// protected members
|
||||
//
|
||||
|
||||
// Derived classes must implement this. When "disposing" is true,
|
||||
// all managed and unmanaged resources are disposed and any references to this
|
||||
// object are released so that the ChangeMonitor can be garbage collected.
|
||||
// It is guaranteed that ChangeMonitor.Dispose() will only invoke
|
||||
// Dispose(bool disposing) once.
|
||||
protected abstract void Dispose(bool disposing);
|
||||
|
||||
// Derived classes must call InitializationComplete
|
||||
protected void InitializationComplete() {
|
||||
_flags[INITIALIZED] = true;
|
||||
|
||||
// If the dependency has already changed, or someone tried to dispose us, then call Dispose now.
|
||||
Dbg.Assert(_flags[INITIALIZED], "It is critical that INITIALIZED is set before CHANGED is checked below");
|
||||
if (_flags[CHANGED]) {
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Derived classes call OnChanged when the dependency changes. Optionally,
|
||||
// they may pass state which will be passed to the OnChangedCallback. The
|
||||
// OnChangedCallback is only invoked once, and only after NotifyOnChanged is
|
||||
// called by the cache implementer. OnChanged is also invoked when the instance
|
||||
// is disposed, but only has an affect if the callback has not already been invoked.
|
||||
protected void OnChanged(Object state) {
|
||||
OnChangedHelper(state);
|
||||
|
||||
// OnChanged will also invoke Dispose, but only after initialization is complete
|
||||
Dbg.Assert(_flags[CHANGED], "It is critical that CHANGED is set before INITIALIZED is checked below.");
|
||||
if (_flags[INITIALIZED]) {
|
||||
DisposeHelper();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// public members
|
||||
//
|
||||
|
||||
// set to true when the dependency changes, specifically, when OnChanged is called.
|
||||
public bool HasChanged { get { return _flags[CHANGED]; } }
|
||||
|
||||
// set to true when this instance is disposed, specifically, after
|
||||
// Dispose(bool disposing) is called by Dispose().
|
||||
public bool IsDisposed { get { return _flags[DISPOSED]; } }
|
||||
|
||||
// a unique ID representing this ChangeMonitor, typically consisting of
|
||||
// the dependency names and last-modified times.
|
||||
public abstract string UniqueId { get; }
|
||||
|
||||
|
||||
// Dispose must be called to release the ChangeMonitor. In order to
|
||||
// prevent derived classes from overriding Dispose, it is not an explicit
|
||||
// interface implementation.
|
||||
//
|
||||
// Before cache insertion, if the user decides not to do a cache insert, they
|
||||
// must call this to dispose the dependency; otherwise, the ChangeMonitor will
|
||||
// be referenced and unable to be garbage collected until the dependency changes.
|
||||
//
|
||||
// After cache insertion, the cache implementer must call this when the cache entry
|
||||
// is removed, for whatever reason. Even if an exception is thrown during insert.
|
||||
//
|
||||
// After cache insertion, the user should not call Dispose. However, since there's
|
||||
// no way to prevent this, doing so will invoke the OnChanged event handler, if it
|
||||
// hasn't already been invoked, and the cache entry will be notified as if the
|
||||
// dependency has changed.
|
||||
//
|
||||
// Dispose() will only invoke the Dispose(bool disposing) method of derived classes
|
||||
// once, the first time it is called. Subsequent calls to Dispose() perform no
|
||||
// operation. After Dispose is called, the IsDisposed property will be true.
|
||||
[SuppressMessage("Microsoft.Performance", "CA1816:DisposeMethodsShouldCallSuppressFinalize", Justification = "Grandfathered suppression from original caching code checkin")]
|
||||
public void Dispose() {
|
||||
OnChangedHelper(null);
|
||||
|
||||
// If not initialized, throw, so the derived class understands that it must call InitializeComplete before Dispose.
|
||||
Dbg.Assert(_flags[CHANGED], "It is critical that CHANGED is set before INITIALIZED is checked below.");
|
||||
if (!_flags[INITIALIZED]) {
|
||||
throw new InvalidOperationException(R.Init_not_complete);
|
||||
}
|
||||
|
||||
DisposeHelper();
|
||||
}
|
||||
|
||||
// Cache implementers must call this to be notified of any dependency changes.
|
||||
// NotifyOnChanged can only be invoked once, and will throw InvalidOperationException
|
||||
// on subsequent calls. The OnChangedCallback is guaranteed to be called exactly once.
|
||||
// It will be called when the dependency changes, or if it has already changed, it will
|
||||
// be called immediately (on the same thread??).
|
||||
public void NotifyOnChanged(OnChangedCallback onChangedCallback) {
|
||||
if (onChangedCallback == null) {
|
||||
throw new ArgumentNullException("onChangedCallback");
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref _onChangedCallback, onChangedCallback, null) != null) {
|
||||
throw new InvalidOperationException(R.Method_already_invoked);
|
||||
}
|
||||
|
||||
// if it already changed, raise the event now.
|
||||
if (_flags[CHANGED]) {
|
||||
OnChanged(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
// <copyright file="CacheSectionGroup.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace System.Runtime.Caching.Configuration {
|
||||
public sealed class CachingSectionGroup : ConfigurationSectionGroup {
|
||||
public CachingSectionGroup() {
|
||||
}
|
||||
|
||||
// public properties
|
||||
[ConfigurationProperty("memoryCache")]
|
||||
public MemoryCacheSection MemoryCaches {
|
||||
get {
|
||||
return (MemoryCacheSection)Sections["memoryCache"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
// <copyright file="ConfigUtil.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Runtime.Caching.Resources;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace System.Runtime.Caching.Configuration {
|
||||
internal static class ConfigUtil {
|
||||
internal const string CacheMemoryLimitMegabytes = "cacheMemoryLimitMegabytes";
|
||||
internal const string PhysicalMemoryLimitPercentage = "physicalMemoryLimitPercentage";
|
||||
internal const string PollingInterval = "pollingInterval";
|
||||
internal const int DefaultPollingTimeMilliseconds = 120000;
|
||||
|
||||
internal static int GetIntValue(NameValueCollection config, string valueName, int defaultValue, bool zeroAllowed, int maxValueAllowed) {
|
||||
string sValue = config[valueName];
|
||||
|
||||
if (sValue == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
int iValue;
|
||||
if (!Int32.TryParse(sValue, out iValue)
|
||||
|| iValue < 0
|
||||
|| (!zeroAllowed && iValue == 0)) {
|
||||
if (zeroAllowed) {
|
||||
throw new ArgumentException(RH.Format(R.Value_must_be_non_negative_integer, valueName, sValue), "config");
|
||||
}
|
||||
|
||||
throw new ArgumentException(RH.Format(R.Value_must_be_positive_integer, valueName, sValue), "config");
|
||||
}
|
||||
|
||||
if (maxValueAllowed > 0 && iValue > maxValueAllowed) {
|
||||
throw new ArgumentException(RH.Format(R.Value_too_big,
|
||||
valueName,
|
||||
sValue,
|
||||
maxValueAllowed.ToString(CultureInfo.InvariantCulture)), "config");
|
||||
}
|
||||
|
||||
return iValue;
|
||||
}
|
||||
|
||||
internal static int GetIntValueFromTimeSpan(NameValueCollection config, string valueName, int defaultValue) {
|
||||
string sValue = config[valueName];
|
||||
|
||||
if (sValue == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (sValue == "Infinite") {
|
||||
return Int32.MaxValue;
|
||||
}
|
||||
|
||||
TimeSpan tValue;
|
||||
if (!TimeSpan.TryParse(sValue, out tValue) || tValue <= TimeSpan.Zero) {
|
||||
throw new ArgumentException(RH.Format(R.TimeSpan_invalid_format, valueName, sValue), "config");
|
||||
}
|
||||
|
||||
double milliseconds = tValue.TotalMilliseconds;
|
||||
int iValue = (milliseconds < (double)Int32.MaxValue) ? (int) milliseconds : Int32.MaxValue;
|
||||
return iValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="MemoryCacheSettingsSettingsCollection.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Runtime.Caching.Configuration {
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Security.Permissions;
|
||||
|
||||
public sealed class MemoryCacheElement : ConfigurationElement {
|
||||
private static ConfigurationPropertyCollection _properties;
|
||||
private static readonly ConfigurationProperty _propName;
|
||||
private static readonly ConfigurationProperty _propPhysicalMemoryLimitPercentage;
|
||||
private static readonly ConfigurationProperty _propCacheMemoryLimitMegabytes;
|
||||
private static readonly ConfigurationProperty _propPollingInterval;
|
||||
|
||||
static MemoryCacheElement() {
|
||||
// Property initialization
|
||||
_properties = new ConfigurationPropertyCollection();
|
||||
|
||||
_propName =
|
||||
new ConfigurationProperty("name",
|
||||
typeof(string),
|
||||
null,
|
||||
new WhiteSpaceTrimStringConverter(),
|
||||
new StringValidator(1),
|
||||
ConfigurationPropertyOptions.IsRequired |
|
||||
ConfigurationPropertyOptions.IsKey);
|
||||
|
||||
_propPhysicalMemoryLimitPercentage =
|
||||
new ConfigurationProperty("physicalMemoryLimitPercentage",
|
||||
typeof(int),
|
||||
(int)0,
|
||||
null,
|
||||
new IntegerValidator(0, 100),
|
||||
ConfigurationPropertyOptions.None);
|
||||
|
||||
_propCacheMemoryLimitMegabytes =
|
||||
new ConfigurationProperty("cacheMemoryLimitMegabytes",
|
||||
typeof(int),
|
||||
(int)0,
|
||||
null,
|
||||
new IntegerValidator(0, Int32.MaxValue),
|
||||
ConfigurationPropertyOptions.None);
|
||||
|
||||
_propPollingInterval =
|
||||
new ConfigurationProperty("pollingInterval",
|
||||
typeof(TimeSpan),
|
||||
TimeSpan.FromMilliseconds(ConfigUtil.DefaultPollingTimeMilliseconds),
|
||||
new InfiniteTimeSpanConverter(),
|
||||
new PositiveTimeSpanValidator(),
|
||||
ConfigurationPropertyOptions.None);
|
||||
|
||||
_properties.Add(_propName);
|
||||
_properties.Add(_propPhysicalMemoryLimitPercentage);
|
||||
_properties.Add(_propCacheMemoryLimitMegabytes);
|
||||
_properties.Add(_propPollingInterval);
|
||||
}
|
||||
|
||||
internal MemoryCacheElement() {
|
||||
}
|
||||
|
||||
public MemoryCacheElement(string name) {
|
||||
Name = name;
|
||||
}
|
||||
|
||||
protected override ConfigurationPropertyCollection Properties {
|
||||
get {
|
||||
return _properties;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("name", DefaultValue = "", IsRequired = true, IsKey = true)]
|
||||
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
|
||||
[StringValidator(MinLength = 1)]
|
||||
public string Name {
|
||||
get {
|
||||
return (string)base["name"];
|
||||
}
|
||||
set {
|
||||
base["name"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("physicalMemoryLimitPercentage", DefaultValue = (int)0)]
|
||||
[IntegerValidator(MinValue = 0, MaxValue = 100)]
|
||||
public int PhysicalMemoryLimitPercentage {
|
||||
get {
|
||||
return (int)base["physicalMemoryLimitPercentage"];
|
||||
}
|
||||
set {
|
||||
base["physicalMemoryLimitPercentage"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("cacheMemoryLimitMegabytes", DefaultValue = (int)0)]
|
||||
[IntegerValidator(MinValue = 0)]
|
||||
public int CacheMemoryLimitMegabytes {
|
||||
get {
|
||||
return (int)base["cacheMemoryLimitMegabytes"];
|
||||
}
|
||||
set {
|
||||
base["cacheMemoryLimitMegabytes"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("pollingInterval", DefaultValue = "00:02:00")]
|
||||
[TypeConverter(typeof(InfiniteTimeSpanConverter))]
|
||||
public TimeSpan PollingInterval {
|
||||
get {
|
||||
return (TimeSpan)base["pollingInterval"];
|
||||
}
|
||||
set {
|
||||
base["pollingInterval"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
// <copyright file="MemoryCacheSection.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.Runtime.Caching.Resources;
|
||||
|
||||
namespace System.Runtime.Caching.Configuration {
|
||||
|
||||
/*
|
||||
<system.runtime.caching>
|
||||
<memoryCaches>
|
||||
<namedCaches>
|
||||
<add name="Default" physicalMemoryPercentage="0" pollingInterval="00:02:00"/>
|
||||
<add name="Foo" physicalMemoryPercentage="0" pollingInterval="00:02:00"/>
|
||||
<add name="Bar" physicalMemoryPercentage="0" pollingInterval="00:02:00"/>
|
||||
</namedCaches>
|
||||
</memoryCaches>
|
||||
</system.caching>
|
||||
|
||||
*/
|
||||
|
||||
public sealed class MemoryCacheSection : ConfigurationSection {
|
||||
private static ConfigurationPropertyCollection _properties;
|
||||
private static readonly ConfigurationProperty _propNamedCaches;
|
||||
|
||||
static MemoryCacheSection() {
|
||||
_propNamedCaches = new ConfigurationProperty("namedCaches",
|
||||
typeof(MemoryCacheSettingsCollection),
|
||||
null, // defaultValue
|
||||
ConfigurationPropertyOptions.None);
|
||||
|
||||
_properties = new ConfigurationPropertyCollection();
|
||||
_properties.Add(_propNamedCaches);
|
||||
}
|
||||
|
||||
public MemoryCacheSection() {
|
||||
}
|
||||
|
||||
protected override ConfigurationPropertyCollection Properties {
|
||||
get {
|
||||
return _properties;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("namedCaches")]
|
||||
public MemoryCacheSettingsCollection NamedCaches {
|
||||
get {
|
||||
return (MemoryCacheSettingsCollection)base[_propNamedCaches];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="MemoryCacheSettingsSettingsCollection.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Runtime.Caching.Configuration {
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Security.Permissions;
|
||||
|
||||
[ConfigurationCollection(typeof(MemoryCacheElement),
|
||||
CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
|
||||
public sealed class MemoryCacheSettingsCollection : ConfigurationElementCollection {
|
||||
private static ConfigurationPropertyCollection _properties;
|
||||
|
||||
static MemoryCacheSettingsCollection() {
|
||||
// Property initialization
|
||||
_properties = new ConfigurationPropertyCollection();
|
||||
}
|
||||
|
||||
protected override ConfigurationPropertyCollection Properties {
|
||||
get {
|
||||
return _properties;
|
||||
}
|
||||
}
|
||||
|
||||
public MemoryCacheSettingsCollection() {
|
||||
}
|
||||
|
||||
public MemoryCacheElement this[int index] {
|
||||
get { return (MemoryCacheElement)base.BaseGet(index); }
|
||||
set {
|
||||
if (base.BaseGet(index) != null) {
|
||||
base.BaseRemoveAt(index);
|
||||
}
|
||||
base.BaseAdd(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public new MemoryCacheElement this[string key] {
|
||||
get {
|
||||
return (MemoryCacheElement)BaseGet(key);
|
||||
}
|
||||
}
|
||||
|
||||
public override ConfigurationElementCollectionType CollectionType {
|
||||
get {
|
||||
return ConfigurationElementCollectionType.AddRemoveClearMapAlternate;
|
||||
}
|
||||
}
|
||||
|
||||
public int IndexOf(MemoryCacheElement cache) {
|
||||
return BaseIndexOf(cache);
|
||||
}
|
||||
|
||||
public void Add(MemoryCacheElement cache) {
|
||||
BaseAdd(cache);
|
||||
}
|
||||
|
||||
public void Remove(MemoryCacheElement cache) {
|
||||
BaseRemove(cache.Name);
|
||||
}
|
||||
|
||||
public void RemoveAt(int index) {
|
||||
BaseRemoveAt(index);
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
BaseClear();
|
||||
}
|
||||
|
||||
protected override ConfigurationElement CreateNewElement() {
|
||||
return new MemoryCacheElement();
|
||||
}
|
||||
|
||||
protected override ConfigurationElement CreateNewElement(string elementName) {
|
||||
return new MemoryCacheElement(elementName);
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element) {
|
||||
return ((MemoryCacheElement)element).Name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
// <copyright file="DefaultCacheCapabilities.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
[Flags]
|
||||
public enum DefaultCacheCapabilities {
|
||||
None = 0x0,
|
||||
InMemoryProvider = 0x1,
|
||||
OutOfProcessProvider = 0x2,
|
||||
CacheEntryChangeMonitors = 0x4,
|
||||
AbsoluteExpirations = 0x8,
|
||||
SlidingExpirations = 0x10,
|
||||
CacheEntryUpdateCallback = 0x20,
|
||||
CacheEntryRemovedCallback = 0x40,
|
||||
CacheRegions = 0x80,
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
// <copyright file="EntryState.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
internal enum EntryState : byte {
|
||||
NotInCache = 0x00, // Created but not in hashtable
|
||||
AddingToCache = 0x01, // In hashtable only
|
||||
AddedToCache = 0x02, // In hashtable + expires + usage
|
||||
RemovingFromCache = 0x04, // Removed from hashtable only
|
||||
RemovedFromCache = 0x08, // Removed from hashtable & expires & usage
|
||||
Closed = 0x10,
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
// <copyright file="FileChangeMonitor.cs" company="Microsoft">
|
||||
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace System.Runtime.Caching {
|
||||
public abstract class FileChangeMonitor : ChangeMonitor {
|
||||
public abstract ReadOnlyCollection<string> FilePaths { get; }
|
||||
public abstract DateTimeOffset LastModified { get; }
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user