WebCache.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. using System;
  2. using System.Configuration;
  3. using System.IO;
  4. using System.Runtime.Serialization.Formatters.Binary;
  5. using System.Web;
  6. using System.Web.Caching;
  7. namespace FastReport.Web
  8. {
  9. /// <summary>
  10. ///
  11. /// </summary>
  12. public class WebReportCache
  13. {
  14. internal static string StoragePrefix = FastReport.Utils.Config.Version + ".";
  15. internal static string touchFilename = StoragePrefix + "touch";
  16. internal static string maskStorage = StoragePrefix + "*";
  17. private bool webFarmMode = false;
  18. private string fileStoragePath;
  19. private int fileStorageTimeout;
  20. private int storageCleanup;
  21. private int cacheDelay = 15;
  22. private CacheItemPriority priority = CacheItemPriority.Default;
  23. private readonly object locker = new object();
  24. /// <summary>
  25. ///
  26. /// </summary>
  27. public bool WebFarmMode
  28. {
  29. get { return webFarmMode; }
  30. }
  31. /// <summary>
  32. ///
  33. /// </summary>
  34. public int Delay
  35. {
  36. get { return cacheDelay; }
  37. set { cacheDelay = value; }
  38. }
  39. /// <summary>
  40. ///
  41. /// </summary>
  42. public CacheItemPriority Priority
  43. {
  44. get { return priority; }
  45. set { priority = value; }
  46. }
  47. /// <summary>
  48. ///
  49. /// </summary>
  50. /// <param name="Name"></param>
  51. /// <param name="Obj"></param>
  52. public void PutObject(string Name, Object Obj)
  53. {
  54. if (Obj != null)
  55. {
  56. lock (locker)
  57. {
  58. if (WebFarmMode)
  59. {
  60. if (Obj is WebReport)
  61. {
  62. WebReport webReport = Obj as WebReport;
  63. using(Stream propStream = webReport.GetPropData())
  64. PutFileStorage(Name, propStream);
  65. using(Stream repStream = webReport.GetReportData())
  66. PutFileStorage(Name + "report", repStream);
  67. using(Stream prepStream = webReport.GetPreparedData())
  68. PutFileStorage(Name + "prepared", prepStream);
  69. }
  70. else
  71. PutFileStorage(Name, Obj);
  72. CleanFileStorage();
  73. }
  74. else
  75. if (!String.IsNullOrEmpty(Name) && Obj != null)
  76. #if DOTNET_4
  77. HttpRuntime.Cache.Insert(
  78. Name,
  79. Obj,
  80. null,
  81. Cache.NoAbsoluteExpiration,
  82. new TimeSpan(0, cacheDelay, 0),
  83. UpdateCallback);
  84. #else
  85. HttpRuntime.Cache.Add(
  86. Name,
  87. Obj,
  88. null,
  89. Cache.NoAbsoluteExpiration,
  90. new TimeSpan(0, cacheDelay, 0),
  91. priority,
  92. RemovedCallback);
  93. #endif
  94. }
  95. }
  96. }
  97. /// <summary>
  98. ///
  99. /// </summary>
  100. /// <param name="Name"></param>
  101. /// <returns></returns>
  102. public object GetObject(string Name)
  103. {
  104. return GetObject(Name, null);
  105. }
  106. /// <summary>
  107. ///
  108. /// </summary>
  109. /// <param name="Name"></param>
  110. /// <param name="obj"></param>
  111. /// <returns></returns>
  112. public object GetObject(string Name, Object obj)
  113. {
  114. lock (locker)
  115. {
  116. if (WebFarmMode)
  117. {
  118. if ((obj != null) && (obj is WebReport))
  119. {
  120. WebReport webReport = obj as WebReport;
  121. using(Stream propStream = GetFileStorage(Name) as Stream)
  122. webReport.SetPropData(propStream);
  123. using (Stream reportStream = GetFileStorage(Name + "report") as Stream)
  124. webReport.SetReportData(reportStream);
  125. using (Stream preparedStream = GetFileStorage(Name + "prepared") as Stream)
  126. webReport.SetPreparedData(preparedStream);
  127. }
  128. else
  129. obj = GetFileStorage(Name);
  130. }
  131. else
  132. if (!String.IsNullOrEmpty(Name))
  133. {
  134. Object cached_obj = HttpRuntime.Cache[Name];
  135. if (cached_obj != null)
  136. obj = cached_obj;
  137. }
  138. }
  139. return obj;
  140. }
  141. /// <summary>
  142. ///
  143. /// </summary>
  144. /// <param name="Name"></param>
  145. public void Remove(string Name)
  146. {
  147. lock (locker)
  148. {
  149. if (!String.IsNullOrEmpty(Name))
  150. {
  151. if (WebFarmMode)
  152. DeleteFileStorage(Name);
  153. else
  154. HttpRuntime.Cache.Remove(Name);
  155. }
  156. }
  157. }
  158. private void DeleteFileStorage(string Name)
  159. {
  160. string fileName = String.Concat(fileStoragePath, StoragePrefix, Name);
  161. if (File.Exists(fileName))
  162. {
  163. try
  164. {
  165. File.Delete(fileName);
  166. }
  167. catch
  168. {
  169. // nothing
  170. }
  171. }
  172. }
  173. private string GetStoragePath(HttpContext context)
  174. {
  175. string path = ConfigurationManager.AppSettings["FastReportStoragePath"];
  176. if (!String.IsNullOrEmpty(path))
  177. {
  178. path += Path.DirectorySeparatorChar;
  179. if (!(path.StartsWith(@"\\") || path.StartsWith(@"//")) && (context != null))
  180. path = context.Request.MapPath(path);
  181. }
  182. return path;
  183. }
  184. private int GetStorageTimeout()
  185. {
  186. string valueS = ConfigurationManager.AppSettings["FastReportStorageTimeout"];
  187. int value = 15;
  188. if (!String.IsNullOrEmpty(valueS))
  189. value = Convert.ToInt16(valueS);
  190. return value;
  191. }
  192. private int GetStorageCleanup()
  193. {
  194. string valueS = ConfigurationManager.AppSettings["FastReportStorageCleanup"];
  195. int value = 1;
  196. if (!String.IsNullOrEmpty(valueS))
  197. value = Convert.ToInt16(valueS);
  198. return value;
  199. }
  200. /// <summary>
  201. ///
  202. /// </summary>
  203. /// <returns></returns>
  204. public int CleanFileStorage()
  205. {
  206. if (webFarmMode)
  207. {
  208. string touch = Path.Combine(fileStoragePath, touchFilename);
  209. if (!String.IsNullOrEmpty(fileStoragePath) && Directory.Exists(fileStoragePath))
  210. {
  211. if (!File.Exists(touch))
  212. {
  213. using (FileStream file = File.Create(touch)) { };
  214. }
  215. else
  216. {
  217. DateTime created = File.GetLastWriteTime(touch);
  218. if (DateTime.Now > created.AddMinutes(storageCleanup))
  219. {
  220. File.SetLastWriteTime(touch, DateTime.Now);
  221. string[] dir = Directory.GetFiles(fileStoragePath, maskStorage);
  222. foreach (string file in dir)
  223. {
  224. try
  225. {
  226. if (DateTime.Now > File.GetLastWriteTime(file).AddMinutes(fileStorageTimeout))
  227. File.Delete(file);
  228. }
  229. catch
  230. {
  231. //nothing
  232. }
  233. }
  234. }
  235. }
  236. }
  237. return Directory.GetFiles(fileStoragePath, maskStorage).Length;
  238. }
  239. else
  240. return 0;
  241. }
  242. private object GetFileStorage(string name)
  243. {
  244. string fileName = String.Concat(fileStoragePath, StoragePrefix, name);
  245. object obj = null;
  246. if (File.Exists(fileName))
  247. {
  248. try
  249. {
  250. File.SetLastWriteTime(fileName, DateTime.Now);
  251. }
  252. catch { };
  253. using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
  254. {
  255. BinaryFormatter bf = new BinaryFormatter();
  256. obj = bf.Deserialize(fs);
  257. }
  258. }
  259. return obj;
  260. }
  261. private void PutFileStorage(string name, object value)
  262. {
  263. string fileName = String.Concat(fileStoragePath, StoragePrefix, name);
  264. if (File.Exists(fileName))
  265. {
  266. if (value is byte[])
  267. {
  268. try
  269. {
  270. File.SetLastWriteTime(fileName, DateTime.Now);
  271. }
  272. catch
  273. {
  274. // nothing to do
  275. }
  276. }
  277. else
  278. try
  279. {
  280. File.Delete(fileName);
  281. }
  282. catch
  283. {
  284. // nothing to do
  285. }
  286. }
  287. if (!File.Exists(fileName))
  288. {
  289. using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
  290. {
  291. BinaryFormatter bf = new BinaryFormatter();
  292. bf.Serialize(fs, value);
  293. }
  294. }
  295. }
  296. #if DOTNET_4
  297. private void UpdateCallback(string key,
  298. CacheItemUpdateReason reason,
  299. out Object expensiveObject,
  300. out CacheDependency dependency,
  301. out DateTime absoluteExpiration,
  302. out TimeSpan slidingExpiration)
  303. {
  304. Object v = HttpRuntime.Cache[key];
  305. dependency = null;
  306. if (v!= null && v is WebReport)
  307. {
  308. WebReport webReport = v as WebReport;
  309. for (int i = 0; i < webReport.Tabs.Count; i++)
  310. {
  311. if (webReport.Tabs[i].Report.PreparedPages != null)
  312. webReport.Tabs[i].Report.PreparedPages.Clear();
  313. webReport.Tabs[i].Properties.ReportDone = false;
  314. }
  315. expensiveObject = v;
  316. absoluteExpiration = Cache.NoAbsoluteExpiration;
  317. slidingExpiration = new TimeSpan(0, cacheDelay, 0);
  318. }
  319. else
  320. {
  321. expensiveObject = null;
  322. absoluteExpiration = DateTime.Now;
  323. slidingExpiration = new TimeSpan(0, 0, 0);
  324. }
  325. }
  326. #else
  327. private void RemovedCallback(String k, Object v, CacheItemRemovedReason r)
  328. {
  329. if (v is WebReport)
  330. {
  331. WebReport webReport = v as WebReport;
  332. try
  333. {
  334. if (webReport.Report.PreparedPages != null)
  335. webReport.Report.PreparedPages.Clear();
  336. webReport.ReportDone = false;
  337. //PutObject(k, webReport);
  338. //webReport.Report.Dispose();
  339. //webReport.Report = null;
  340. }
  341. catch
  342. {
  343. // nothing
  344. }
  345. }
  346. }
  347. #endif
  348. /// <summary>
  349. ///
  350. /// </summary>
  351. /// <param name="context"></param>
  352. public WebReportCache(HttpContext context)
  353. {
  354. fileStoragePath = GetStoragePath(context);
  355. webFarmMode = !String.IsNullOrEmpty(fileStoragePath);
  356. fileStorageTimeout = GetStorageTimeout();
  357. storageCleanup = GetStorageCleanup();
  358. }
  359. }
  360. }