From a49ccf4d7617c13ffa965732ecbfe99764ab8893 Mon Sep 17 00:00:00 2001 From: StanleyGoldman Date: Thu, 25 Apr 2013 10:53:39 -0400 Subject: [PATCH] #19646: Fixing media processing cache * Adding logging to prove issue #19646 * Removing suspect not operator * Refactoring complex if statement * Temporary try/catch's to find exception * Refactor GetImagePathType out of GetImage * Properly checking for an images last update time Work Item: 19646 --HG-- branch : 1.x extra : rebase_source : b5444740cf57e936499af129d9b4306e782596ba --- .../Shapes/MediaShapes.cs | 120 ++++++++++++++---- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs index ef3ef031a..25d0f7bb2 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaProcessing/Shapes/MediaShapes.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Net; using System.Web; +using System.Web.Hosting; using Orchard.ContentManagement; using Orchard.DisplayManagement; using Orchard.Environment; @@ -19,7 +20,7 @@ using Orchard.Tokens; using Orchard.Utility.Extensions; namespace Orchard.MediaProcessing.Shapes { - + public class MediaShapes : IDependency { private readonly Work _storageProvider; private readonly Work _fileNameProvider; @@ -75,7 +76,7 @@ namespace Orchard.MediaProcessing.Shapes { [Shape] public void MediaUrl(dynamic Shape, dynamic Display, TextWriter Output, string Profile, string Path, ContentItem ContentItem, FilterRecord CustomFilter) { try { - Shape.IgnoreShapeTracer = true; + Shape.IgnoreShapeTracer = true; var services = new Lazy(() => _services.Value); var storageProvider = new Lazy(() => _storageProvider.Value); @@ -84,22 +85,38 @@ namespace Orchard.MediaProcessing.Shapes { bool process = false; // if the filename is not cached, process it - if (!string.IsNullOrEmpty(filePath)) { + if (string.IsNullOrEmpty(filePath)) { + Logger.Debug("FilePath is null, processing required, profile {0} for image {1}", Profile, Path); + process = true; } // the processd file doesn't exist anymore, process it else if (!storageProvider.Value.FileExists(filePath)) { + Logger.Debug("Processed file no longer exists, processing required, profile {0} for image {1}", Profile, Path); + process = true; } - // if the original file is more recent, process it - else if (storageProvider.Value.GetFile(Path).GetLastUpdated() > storageProvider.Value.GetFile(filePath).GetLastUpdated()) { - process = true; + // if the original file is more recent, process it + else { + DateTime pathLastUpdated; + if (TryGetImageLastUpdated(Path, out pathLastUpdated)) { + var filePathLastUpdated = storageProvider.Value.GetFile(filePath).GetLastUpdated(); + + if (pathLastUpdated > filePathLastUpdated) + { + Logger.Debug("Original file more recent, processing required, profile {0} for image {1}", Profile, Path); + + process = true; + } + } } // todo: regenerate the file if the profile is newer, by deleting the associated filename cache entries. if (process) { + Logger.Debug("Processing profile {0} for image {1}", Profile, Path); + ImageProfilePart profilePart; if (CustomFilter == null) { @@ -113,7 +130,8 @@ namespace Orchard.MediaProcessing.Shapes { } using (var image = GetImage(Path)) { - var filterContext = new FilterContext {Media = image, Format = new FileInfo(Path).Extension, FilePath = storageProvider.Value.Combine(Profile, CreateDefaultFileName(Path))}; + + var filterContext = new FilterContext { Media = image, Format = new FileInfo(Path).Extension, FilePath = storageProvider.Value.Combine(Profile, CreateDefaultFileName(Path)) }; var tokens = new Dictionary(); // if a content item is provided, use it while tokenizing @@ -167,34 +185,84 @@ namespace Orchard.MediaProcessing.Shapes { } } - // TODO: Update this method once the storage provider has been updated - private Stream GetImage(string path) { - var storageProvider = new Lazy(() => _storageProvider.Value); - var services = new Lazy(() => _services.Value); - - var request = services.Value.WorkContext.HttpContext.Request; + private enum ImagePathType + { + StorageProvider, + AbsoluteUrl, + AppRelative, + Invalid + } + private ImagePathType GetImagePathType(string path) { // /OrchardLocal/images/my-image.jpg if (Uri.IsWellFormedUriString(path, UriKind.Relative)) { - path = storageProvider.Value.GetLocalPath(path); - - // images/my-image.jpg - var file = storageProvider.Value.GetFile(path); - return file.OpenRead(); + return ImagePathType.StorageProvider; } // http://blob.storage-provider.net/my-image.jpg if (Uri.IsWellFormedUriString(path, UriKind.Absolute)) { - var webClient = new WebClient(); - return webClient.OpenRead(new Uri(path)); - } - // ~/Media/Default/images/my-image.jpg - if (VirtualPathUtility.IsAppRelative(path)) { - var webClient = new WebClient(); - return webClient.OpenRead(new Uri(request.Url, VirtualPathUtility.ToAbsolute(path))); + return ImagePathType.AbsoluteUrl; } - throw new ArgumentException("invalid path"); + // ~/Media/Default/images/my-image.jpg + if (VirtualPathUtility.IsAppRelative(path)) { + return ImagePathType.AppRelative; + } + + return ImagePathType.Invalid; + } + + // TODO: Update this method once the storage provider has been updated + private Stream GetImage(string path) { + var storageProvider = new Lazy(() => _storageProvider.Value); + var services = new Lazy(() => _services.Value); + var webClient = new Lazy(() => new WebClient()); + + var request = services.Value.WorkContext.HttpContext.Request; + + switch (GetImagePathType(path)) { + case ImagePathType.StorageProvider: + path = storageProvider.Value.GetLocalPath(path); + + // images/my-image.jpg + var file = storageProvider.Value.GetFile(path); + return file.OpenRead(); + + case ImagePathType.AbsoluteUrl: + return webClient.Value.OpenRead(new Uri(path)); + + case ImagePathType.AppRelative: + return webClient.Value.OpenRead(new Uri(request.Url, VirtualPathUtility.ToAbsolute(path))); + + default: + throw new ArgumentException("invalid path"); + } + } + + private bool TryGetImageLastUpdated(string path, out DateTime lastUpdated) { + var imagePathType = GetImagePathType(path); + switch (imagePathType) + { + case ImagePathType.StorageProvider: + path = _storageProvider.Value.GetLocalPath(path); + + var file = _storageProvider.Value.GetFile(path); + lastUpdated = file.GetLastUpdated(); + + return true; + + case ImagePathType.AppRelative: + var serverPath = HostingEnvironment.MapPath(path); + lastUpdated = File.GetLastWriteTime(serverPath); + + return true; + + default: + Logger.Warning("Cannot get last updated time for {0}, {1}", imagePathType, path); + + lastUpdated = DateTime.MinValue; + return false; + } } private static string CreateDefaultFileName(string path) {