PageRenderTime 62ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/Orchard.Web/Modules/Orchard.Warmup/Services/WarmupUpdater.cs

https://bitbucket.org/oleg_ator/orchard.test
C# | 204 lines | 161 code | 28 blank | 15 comment | 18 complexity | fa5a0ac3482267512a6f7da17cf532cc MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Net;
  5. using System.Web;
  6. using System.Xml;
  7. using Orchard.ContentManagement;
  8. using Orchard.Environment.Configuration;
  9. using Orchard.Environment.Warmup;
  10. using Orchard.FileSystems.AppData;
  11. using Orchard.FileSystems.LockFile;
  12. using Orchard.Logging;
  13. using Orchard.Services;
  14. using Orchard.Warmup.Models;
  15. namespace Orchard.Warmup.Services {
  16. public class WarmupUpdater : IWarmupUpdater {
  17. private readonly IOrchardServices _orchardServices;
  18. private readonly ILockFileManager _lockFileManager;
  19. private readonly IClock _clock;
  20. private readonly IAppDataFolder _appDataFolder;
  21. private readonly IWebDownloader _webDownloader;
  22. private readonly IWarmupReportManager _reportManager;
  23. private const string BaseFolder = "Warmup";
  24. private const string WarmupFilename = "warmup.txt";
  25. private readonly string _warmupPath;
  26. private readonly string _lockFilename;
  27. public WarmupUpdater(
  28. IOrchardServices orchardServices,
  29. ILockFileManager lockFileManager,
  30. IClock clock,
  31. IAppDataFolder appDataFolder,
  32. IWebDownloader webDownloader,
  33. IWarmupReportManager reportManager,
  34. ShellSettings shellSettings) {
  35. _orchardServices = orchardServices;
  36. _lockFileManager = lockFileManager;
  37. _clock = clock;
  38. _appDataFolder = appDataFolder;
  39. _webDownloader = webDownloader;
  40. _reportManager = reportManager;
  41. _lockFilename = _appDataFolder.Combine("Sites", _appDataFolder.Combine(shellSettings.Name, WarmupFilename + ".lock"));
  42. _warmupPath = _appDataFolder.Combine("Sites", _appDataFolder.Combine(shellSettings.Name, WarmupFilename));
  43. Logger = NullLogger.Instance;
  44. }
  45. public ILogger Logger { get; set; }
  46. public void EnsureGenerate() {
  47. var baseUrl = _orchardServices.WorkContext.CurrentSite.BaseUrl;
  48. var part = _orchardServices.WorkContext.CurrentSite.As<WarmupSettingsPart>();
  49. // do nothing while the base url setting is not defined
  50. if (String.IsNullOrWhiteSpace(baseUrl)) {
  51. return;
  52. }
  53. // prevent multiple appdomains from rebuilding the static page concurrently (e.g., command line)
  54. ILockFile lockFile = null;
  55. if (!_lockFileManager.TryAcquireLock(_lockFilename, ref lockFile)) {
  56. return;
  57. }
  58. using (lockFile) {
  59. // check if we need to regenerate the pages by reading the last time it has been done
  60. // 1- if the warmup file doesn't exists, generate the pages
  61. // 2- otherwise, if the scheduled generation option is on, check if the delay is over
  62. if (_appDataFolder.FileExists(_warmupPath)) {
  63. try {
  64. var warmupContent = _appDataFolder.ReadFile(_warmupPath);
  65. var expired = XmlConvert.ToDateTimeOffset(warmupContent).AddMinutes(part.Delay);
  66. if (expired > _clock.UtcNow) {
  67. return;
  68. }
  69. }
  70. catch {
  71. // invalid file, delete continue processing
  72. _appDataFolder.DeleteFile(_warmupPath);
  73. }
  74. }
  75. // delete peviously generated pages, by reading the Warmup Report file
  76. try {
  77. var encodedPrefix = WarmupUtility.EncodeUrl("http://www.");
  78. foreach (var reportEntry in _reportManager.Read()) {
  79. try {
  80. // use FileName as the SiteBaseUrl could have changed in the meantime
  81. var path = _appDataFolder.Combine(BaseFolder, reportEntry.Filename);
  82. _appDataFolder.DeleteFile(path);
  83. // delete the www-less version too if it's available
  84. if (reportEntry.Filename.StartsWith(encodedPrefix, StringComparison.OrdinalIgnoreCase)) {
  85. var filename = WarmupUtility.EncodeUrl("http://") + reportEntry.Filename.Substring(encodedPrefix.Length);
  86. path = _appDataFolder.Combine(BaseFolder, filename);
  87. _appDataFolder.DeleteFile(path);
  88. }
  89. }
  90. catch (Exception e) {
  91. Logger.Error(e, "Could not delete specific warmup file: ", reportEntry.Filename);
  92. }
  93. }
  94. }
  95. catch(Exception e) {
  96. Logger.Error(e, "Could not read warmup report file");
  97. }
  98. var reportEntries = new List<ReportEntry>();
  99. if (!String.IsNullOrEmpty(part.Urls)) {
  100. // loop over every relative url to generate the contents
  101. using (var urlReader = new StringReader(part.Urls)) {
  102. string relativeUrl;
  103. while (null != (relativeUrl = urlReader.ReadLine())) {
  104. if (String.IsNullOrWhiteSpace(relativeUrl)) {
  105. continue;
  106. }
  107. string url = null;
  108. relativeUrl = relativeUrl.Trim();
  109. try {
  110. url = VirtualPathUtility.RemoveTrailingSlash(baseUrl) + relativeUrl;
  111. var filename = WarmupUtility.EncodeUrl(url.TrimEnd('/'));
  112. var path = _appDataFolder.Combine(BaseFolder, filename);
  113. var download = _webDownloader.Download(url);
  114. if (download != null) {
  115. if (download.StatusCode == HttpStatusCode.OK) {
  116. // success
  117. _appDataFolder.CreateFile(path, download.Content);
  118. reportEntries.Add(new ReportEntry {
  119. RelativeUrl = relativeUrl,
  120. Filename = filename,
  121. StatusCode = (int) download.StatusCode,
  122. CreatedUtc = _clock.UtcNow
  123. });
  124. // if the base url contains http://www, then also render the www-less one);
  125. if (url.StartsWith("http://www.", StringComparison.OrdinalIgnoreCase)) {
  126. url = "http://" + url.Substring("http://www.".Length);
  127. filename = WarmupUtility.EncodeUrl(url.TrimEnd('/'));
  128. path = _appDataFolder.Combine(BaseFolder, filename);
  129. _appDataFolder.CreateFile(path, download.Content);
  130. }
  131. }
  132. else {
  133. reportEntries.Add(new ReportEntry {
  134. RelativeUrl = relativeUrl,
  135. Filename = filename,
  136. StatusCode = (int) download.StatusCode,
  137. CreatedUtc = _clock.UtcNow
  138. });
  139. }
  140. }
  141. else {
  142. // download failed
  143. reportEntries.Add(new ReportEntry {
  144. RelativeUrl = relativeUrl,
  145. Filename = filename,
  146. StatusCode = 0,
  147. CreatedUtc = _clock.UtcNow
  148. });
  149. }
  150. }
  151. catch (Exception e) {
  152. Logger.Error(e, "Could not extract warmup page content for: ", url);
  153. }
  154. }
  155. }
  156. }
  157. _reportManager.Create(reportEntries);
  158. // finally write the time the generation has been executed
  159. _appDataFolder.CreateFile(_warmupPath, XmlConvert.ToString(_clock.UtcNow, XmlDateTimeSerializationMode.Utc));
  160. }
  161. }
  162. public void Generate() {
  163. // prevent multiple appdomains from rebuilding the static page concurrently (e.g., command line)
  164. ILockFile lockFile = null;
  165. if (!_lockFileManager.TryAcquireLock(_lockFilename, ref lockFile)) {
  166. return;
  167. }
  168. using (lockFile) {
  169. if (_appDataFolder.FileExists(_warmupPath)) {
  170. _appDataFolder.DeleteFile(_warmupPath);
  171. }
  172. }
  173. EnsureGenerate();
  174. }
  175. }
  176. }