CacheDependency.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // System.Web.Caching.CacheDependency
  3. //
  4. // Authors:
  5. // Patrik Torstensson ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // (C) Copyright Patrik Torstensson, 2001
  9. // (c) 2003 Ximian, Inc. (http://www.ximian.com)
  10. //
  11. using System;
  12. using System.IO;
  13. using System.Web;
  14. namespace System.Web.Caching
  15. {
  16. internal class CacheDependencyChangedArgs : EventArgs
  17. {
  18. string key;
  19. public CacheDependencyChangedArgs (string key)
  20. {
  21. this.key = key;
  22. }
  23. public string Key {
  24. get { return key; }
  25. }
  26. }
  27. internal delegate void CacheDependencyChangedHandler (object sender, CacheDependencyChangedArgs args);
  28. public sealed class CacheDependency : IDisposable
  29. {
  30. static string [] noStrings = new string [0];
  31. static CacheDependency noDependency = new CacheDependency ();
  32. DateTime start;
  33. bool changed;
  34. bool disposed;
  35. CacheEntry [] entries;
  36. CacheItemRemovedCallback removedDelegate;
  37. FileSystemWatcher [] watchers;
  38. private CacheDependency ()
  39. {
  40. }
  41. public CacheDependency (string filename)
  42. : this (filename, DateTime.MaxValue)
  43. {
  44. }
  45. public CacheDependency (string filename, DateTime start)
  46. : this (new string [] {filename}, null, null, start)
  47. {
  48. }
  49. public CacheDependency (string [] filenames)
  50. : this (filenames, null, null, DateTime.MaxValue)
  51. {
  52. }
  53. public CacheDependency (string [] filenames, DateTime start)
  54. : this (filenames, null, null, start)
  55. {
  56. }
  57. public CacheDependency (string [] filenames, string [] cachekeys)
  58. : this (filenames, cachekeys, null, DateTime.MaxValue)
  59. {
  60. }
  61. public CacheDependency (string [] filenames, string [] cachekeys, DateTime start)
  62. : this (filenames, cachekeys, null, start)
  63. {
  64. }
  65. public CacheDependency (string [] filenames, string [] cachekeys, CacheDependency dependency)
  66. : this (filenames, cachekeys, dependency, DateTime.MaxValue)
  67. {
  68. }
  69. public CacheDependency (string [] filenames,
  70. string [] cachekeys,
  71. CacheDependency dependency,
  72. DateTime start)
  73. {
  74. Cache cache = HttpRuntime.Cache;
  75. this.start = start;
  76. if (filenames == null)
  77. filenames = noStrings;
  78. foreach (string file in filenames) {
  79. if (file == null)
  80. throw new ArgumentNullException ("filenames");
  81. }
  82. if (cachekeys == null)
  83. cachekeys = noStrings;
  84. int missing_keys = 0;
  85. foreach (string ck in cachekeys) {
  86. if (ck == null)
  87. throw new ArgumentNullException ("cachekeys");
  88. if (cache.GetEntry (ck) == null)
  89. missing_keys++;
  90. }
  91. if (dependency == null)
  92. dependency = noDependency;
  93. this.changed = dependency.changed;
  94. if (changed == true)
  95. return;
  96. int nentries = cachekeys.Length + ((dependency.entries == null) ? 0 :
  97. dependency.entries.Length) - missing_keys;
  98. if (nentries != 0) {
  99. this.removedDelegate = new CacheItemRemovedCallback (CacheItemRemoved);
  100. this.entries = new CacheEntry [nentries];
  101. int i = 0;
  102. if (dependency.entries != null) {
  103. foreach (CacheEntry entry in dependency.entries) {
  104. entry._onRemoved += removedDelegate;
  105. entries [i++] = entry;
  106. }
  107. }
  108. for (int c=0; c<cachekeys.Length; c++) {
  109. CacheEntry entry = cache.GetEntry (cachekeys [c]);
  110. if (entry == null)
  111. continue;
  112. entry._onRemoved += removedDelegate;
  113. entries [i++] = entry;
  114. }
  115. }
  116. if (filenames.Length > 0) {
  117. watchers = new FileSystemWatcher [filenames.Length];
  118. for (int i=0; i<filenames.Length; i++)
  119. watchers [i] = CreateWatcher (filenames [i]);
  120. }
  121. }
  122. private FileSystemWatcher CreateWatcher (string file)
  123. {
  124. FileSystemWatcher watcher = new FileSystemWatcher ();
  125. watcher.Path = Path.GetFullPath (Path.GetDirectoryName (file));
  126. watcher.Filter = Path.GetFileName (file);
  127. watcher.Changed += new FileSystemEventHandler (OnFileChanged);
  128. watcher.Created += new FileSystemEventHandler (OnFileChanged);
  129. watcher.Deleted += new FileSystemEventHandler (OnFileChanged);
  130. watcher.EnableRaisingEvents = true;
  131. return watcher;
  132. }
  133. private void OnFileChanged (object sender, FileSystemEventArgs e)
  134. {
  135. OnChanged (sender, e);
  136. }
  137. void CacheItemRemoved (string key, object value, CacheItemRemovedReason reason)
  138. {
  139. OnChanged (this, EventArgs.Empty);
  140. }
  141. void OnChanged (object sender, EventArgs args)
  142. {
  143. if (changed || disposed)
  144. return;
  145. changed = true;
  146. if (Changed != null)
  147. Changed (this, new CacheDependencyChangedArgs (null));
  148. }
  149. public void Dispose ()
  150. {
  151. for (int i=0; i<watchers.Length; i++)
  152. watchers [i].Dispose ();
  153. }
  154. public bool HasChanged
  155. {
  156. get { return changed; }
  157. }
  158. internal CacheEntry [] GetCacheEntries ()
  159. {
  160. return entries;
  161. }
  162. internal event CacheDependencyChangedHandler Changed;
  163. }
  164. }