-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathMemoryCacheEntryChangeMonitor.cs
More file actions
127 lines (117 loc) · 5.25 KB
/
MemoryCacheEntryChangeMonitor.cs
File metadata and controls
127 lines (117 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// <copyright file="MemoryCacheEntryChangeMonitor.cs" company="Microsoft">
// Copyright (c) 2009 Microsoft Corporation. All rights reserved.
// </copyright>
using System;
using System.Runtime.Caching.Resources;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
namespace System.Runtime.Caching {
internal sealed class MemoryCacheEntryChangeMonitor : CacheEntryChangeMonitor {
// Dev10 909507: use UTC minimum DateTime for error free conversions to DateTimeOffset
private static readonly DateTime DATETIME_MINVALUE_UTC = new DateTime(0, DateTimeKind.Utc);
private const int MAX_CHAR_COUNT_OF_LONG_CONVERTED_TO_HEXADECIMAL_STRING = 16;
private ReadOnlyCollection<String> _keys;
private String _regionName;
private String _uniqueId;
private DateTimeOffset _lastModified;
private List<MemoryCacheEntry> _dependencies;
private MemoryCacheEntryChangeMonitor() {} // hide default .ctor
private void InitDisposableMembers(MemoryCache cache) {
bool dispose = true;
try {
bool hasChanged = false;
string uniqueId = null;
_dependencies = new List<MemoryCacheEntry>(_keys.Count);
if (_keys.Count == 1) {
string k = _keys[0];
MemoryCacheEntry entry = cache.GetEntry(k);
DateTime utcCreated = DATETIME_MINVALUE_UTC;
StartMonitoring(cache, entry, ref hasChanged, ref utcCreated);
uniqueId = k + utcCreated.Ticks.ToString("X", CultureInfo.InvariantCulture);
_lastModified = utcCreated;
}
else {
int capacity = 0;
foreach (string key in _keys) {
capacity += key.Length + MAX_CHAR_COUNT_OF_LONG_CONVERTED_TO_HEXADECIMAL_STRING;
}
StringBuilder sb = new StringBuilder(capacity);
foreach (string key in _keys) {
MemoryCacheEntry entry = cache.GetEntry(key);
DateTime utcCreated = DATETIME_MINVALUE_UTC;
StartMonitoring(cache, entry, ref hasChanged, ref utcCreated);
sb.Append(key);
sb.Append(utcCreated.Ticks.ToString("X", CultureInfo.InvariantCulture));
if (utcCreated > _lastModified) {
_lastModified = utcCreated;
}
}
uniqueId = sb.ToString();
}
_uniqueId = uniqueId;
if (hasChanged) {
OnChanged(null);
}
dispose = false;
}
finally {
InitializationComplete();
if (dispose) {
Dispose();
}
}
}
private void StartMonitoring(MemoryCache cache, MemoryCacheEntry entry, ref bool hasChanged, ref DateTime utcCreated) {
if (entry != null) {
// pass reference to self so the dependency can notify us when it changes
entry.AddDependent(cache, this);
// add dependency to collection so we can dispose it later
_dependencies.Add(entry);
// has the entry already changed?
if (entry.State != EntryState.AddedToCache) {
hasChanged = true;
}
utcCreated = entry.UtcCreated;
}
else {
// the entry does not exist--set hasChanged to true so the user is notified
hasChanged = true;
}
}
//
// protected members
//
protected override void Dispose(bool disposing) {
if (disposing) {
if (_dependencies != null) {
foreach (MemoryCacheEntry entry in _dependencies) {
if (entry != null) {
entry.RemoveDependent(this);
}
}
}
}
}
//
// public and internal members
//
public override ReadOnlyCollection<string> CacheKeys { get { return new ReadOnlyCollection<string>(_keys); } }
public override string RegionName { get { return _regionName; } }
public override string UniqueId { get { return _uniqueId; } }
public override DateTimeOffset LastModified { get { return _lastModified; } }
internal List<MemoryCacheEntry> Dependencies { get { return _dependencies; } }
internal MemoryCacheEntryChangeMonitor(ReadOnlyCollection<String> keys, String regionName, MemoryCache cache) {
Dbg.Assert(keys != null && keys.Count > 0, "keys != null && keys.Count > 0");
_keys = keys;
_regionName = regionName;
InitDisposableMembers(cache);
}
// invoked by a cache entry dependency when it is released from the cache
internal void OnCacheEntryReleased() {
OnChanged(null);
}
}
}