Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -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; }
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}

View File

@@ -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
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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"];
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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];
}
}
}
}

View File

@@ -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

View File

@@ -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,
}
}

View File

@@ -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,
}
}

View File

@@ -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